各种函数区别
曾经了解过各种函数之间的区别,但是不能深入理解其区别。实践之后才明白这些道理和区别,成长就是不断学习的过程。
1、内联函数和普通函数的区别
1-1、总结
内联函数和普通函数最大的区别在于内部的实现方面,当普通函数在被调用时,系统首先跳跃到该函数的入口地址,执行函数体,执行完成后,再返回到函数调用的地方,函数始终只有一个拷贝; 而内联函数则不需要进行一个寻址的过程,当执行到内联函数时,此函数展开(很类似宏的使用),如果在 N处调用了此内联函数,则此函数就会有N个代码段的拷贝。
1-2、详细说明
内联函数和普通函数的主要区别在于它们的编译方式和执行效率。
普通函数是在程序运行时被调用的,每次调用都会将控制权转移到函数体中执行,执行完毕后再返回到调用点。这种方式会涉及到函数调用的开销,包括压栈、跳转等操作,因此在频繁调用的情况下,会影响程序的执行效率。
内联函数则是在编译时被展开的,编译器会将函数体直接嵌入到调用点处,避免了函数调用的开销。这种方式可以提高程序的执行效率,特别是对于一些简单的、频繁调用的函数,如取绝对值、计算平方等。
另外,内联函数还有以下特点:
- 内联函数通常比普通函数更小,因为它们不需要保存和恢复调用现场。
- 内联函数不能递归调用自身,因为编译器无法展开无限递归的函数。
- 内联函数的定义通常放在头文件中,以便在多个源文件中使用。
需要注意的是,内联函数并不是在所有情况下都比普通函数更优秀。如果内联函数过于复杂,展开后会导致代码膨胀,反而会降低程序的执行效率。因此,应该根据具体情况来选择使用内联函数还是普通函数。
2、静态函数和普通函数的区别
2-1、总结
static函数和普通函数的最大的区别在于作用域方面,static函数限定在本源码文件中,不能被本源码文件以外的代码文件调用。而普通的函数,默认是extern的,也就是说,可以被其它代码文件调用该函数。同时static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝。
2-2、详细说明
静态函数和普通函数的主要区别在于它们的作用域和可见性。
普通函数的作用域是全局的,可以被程序中的任何函数调用。如果函数的定义没有被放在头文件中,那么在其他源文件中调用该函数时,需要使用函数声明来告诉编译器该函数的返回类型和参数类型。普通函数的可见性是全局的,因此容易被其他源文件中的函数调用,也容易被其他库文件中的函数调用。
静态函数的作用域是局部的,只能在定义该函数的源文件中被调用。静态函数的可见性是局部的,因此不容易被其他源文件或库文件中的函数调用。这种特性可以避免函数名冲突,提高程序的安全性和可维护性。
另外,静态函数还有以下特点:
- 静态函数只能在定义它的源文件中被调用,因此可以避免函数名冲突,提高程序的安全性和可维护性。
- 静态函数的生命周期与程序的生命周期相同,即在程序启动时被加载到内存中,直到程序结束时才被释放。
- 静态函数不能被其他源文件或库文件中的函数调用,因此可以避免函数名冲突,提高程序的安全性和可维护性。
需要注意的是,静态函数并不是在所有情况下都比普通函数更优秀。如果函数需要在多个源文件中被调用,那么应该使用普通函数。如果函数只在一个源文件中被调用,那么应该使用静态函数。
2-3、静态成员函数中尝试访问一个非静态成员变量
报错:error: invalid use of member ‘SystemTray::mSessTypes’ in static member function 静态成员函数不能直接访问类的非静态成员变量或非静态成员函数,因为静态成员函数不属于任何特定的对象实例,而是属于类本身。
报错:
error: cannot convert ‘SystemTray::HandlerCurSessInfo’ from type ‘int (SystemTray::)(const SfJsonParamsObj&, QString&)’ {aka ‘int (SystemTray::)(const _SfJsonParamsObj&, QString&)’} to type ‘std::map<std::__cxx11::basic_string<char>, int (*)(const _SfJsonParamsObj&, QString&)>::mapped_type’ {aka ‘int (*)(const _SfJsonParamsObj&, QString&)’}试图将一个成员函数指针赋值给一个普通函数指针。这是因为成员函数的指针和普通函数的指针在 C++ 中是不同的。 在 C++ 中,成员函数的指针需要一个对象实例来调用,而普通函数的指针不需要。因此,您不能直接将一个成员函数指针赋值给一个期望普通函数指针的地方。 解决方式:可以将其定义为静态成员函数。静态成员函数的指针可以被视为普通函数指针。
在 C++ 中,this 指针是一个隐式参数,指向当前对象的实例。您可以在非静态成员函数中使用 this 指针,但在静态成员函数或普通函数中不能直接使用 this 指针,因为它们不属于任何特定的对象实例。 解决方式:
类中定义:
public:
static SystemTray* s_this; //静态指针,用于回调函数中类成员函数以及信号的调用
类的构造函数中赋值:
s_this = this;
然后就可以在静态函数中使用s_this指针访问成员变量。3、内联函数和宏的区别
答:为什么要使用宏呢?因为函数的调用必须要将程序执行的顺序转移到函数所存放在内存中的某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去执行前要保存现场并记忆执行的地址,转回后要恢复现场,并按原来保存地址继续执行。因此,函数调用要有一定的时间和空间方面的开销,于是将影响其效率。而宏只是在预处理的地方把代码展开,不需要额外的空间和时间方面的开销,所以调用一个宏比调用一个函数更有效率。
但是宏也有很多的不尽人意的地方。比如,宏不能访问对象的私有成员,还有宏的定义很容易产生二义性。
4、到底什么是内联函数?
GCC中的inline函数可以相当于在一个普通的全局函数加上inline属性。inline关键字仅仅是建议编译器在编译的时候做内联展开处理,而不是强制在gcc编译器中,如果吧编译选项设置为负无穷,即使是inline函数也不会被内联展开,除非设置了强制内联展开的属性(attribute((always_inline)))。
5、静态函数有什么特点?
静态函数又称为内部函数。在C/C++中,定义的函数默认都是全局的(相对于多个文件的源程序)。而在函数的前面加上static关键字可以改变函数的作用域,即将函数的作用域限定在含有此函数的定义所在的文件,在其他文件中不可以使用此函数。
静态函数作用呢: 1,起隐藏作用,静态函数只能在本文件中被访问,而不能被除此文件外的其他文件所使用。 2,使用静态函数可以在其他文件中定义同名的函数,而不用考虑会出现名字冲突或者冲定义的错误。
6、静态函数的内存分配
static只会改变(限制)函数的作用域,而不会像静态变量那样改变变量的存储位置。static的函数和普通函数的内存存储区域以及内存分配方式是相同的。
7、内联函数和静态函数区别
内联函数(inline function)和静态函数(static function)是 C++ 中的两种不同概念。
内联函数 主要用于提高性能,减少函数调用的开销。编译器在调用内联函数时,会尝试将函数的代码直接插入到调用点,而不是进行常规的函数调用。作用域与普通函数相同,可以在多个文件中被调用(如果在头文件中定义)。但过度使用内联函数可能导致代码膨胀,因为每次调用都会插入函数体。
静态函数 主要用于控制作用域,限制函数的可见性,避免命名冲突。使其只能在定义它的文件中可见,无法被其他文件访问。这通常用于实现模块化和封装。
7-1、使用场景
内联函数: 适用于小型、频繁调用的函数,例如简单的 getter/setter 函数或数学计算函数。
静态函数: 适用于需要封装实现细节的函数,或者在一个源文件中使用而不希望被其他文件访问的函数。