1.权限放大和缩小
我们可以发现这里的权限放大是编译不通过的,其他都是可以的。
2.内联函数 inline
内联函数是一种编译器优化手段,它的主要作用是减少函数调用的开销,提高程序的执行效率。
一方面,函数调用通常会涉及栈帧的创建和销毁,以及参数的传递和返回值的处理等操作,这些操作都会导致额外的时间和空间开销。而内联函数会将函数体直接插入到调用位置,避免了这些操作,从而减少了执行时间。
另一方面,内联函数的插入是由编译器自动完成的,它可以对函数体进行更多的优化,比如常量折叠、循环展开等,从而进一步提高程序的执行效率。
总的来说,内联函数的意义和作用主要体现在两个方面:
1. 减少函数调用的开销,提高程序的执行效率;
2. 进一步优化函数体,提高程序的执行效率。
我们知道在调用函数时,就会相应的开辟栈帧,内联函数就是将函数展开在执行的地方,这样就可以减少调用的开销。但是需要注意的是内联函数只是一种建议,具体执不执行害得看编译器。
这里我们需要调用多次add函数,如果每次调用都创建栈帧就消耗过大,如果我们将其改为内联函数,那么就可以展开在调用的地方,就可以不用多开辟栈帧。
需要注意的是 在debug模式下,需要对编译器进行设置,否则不会展开(因为debug模式下,编译器默认不会对代码进行优化。
虽然内联函数具有提高程序执行效率的优点,但也存在一些缺点:
-
代码膨胀:内联函数会将函数体直接插入到调用位置,如果函数体过长或者被频繁调用,那么会导致代码膨胀,增加可执行文件的大小。
-
编译时间增加:内联函数需要在编译阶段进行函数体的插入,如果有大量的内联函数,会增加编译时间。
-
编译器决策:内联函数的最终决策是由编译器完成的,无法直接控制内联,有些编译器可能会选择不将函数内联,导致无法实现预期的优化效果。
-
可维护性降低:内联函数的定义和实现通常放在头文件中,如果内联函数发生了改变,会导致所有调用该函数的地方都需要重新编译。
总结:
1.inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替 换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率。
2. inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建议:将函数规 模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、频繁调用的函数 采用inline修饰,否则编译器会忽略inline特性。
3.使用内联函数需要谨慎,并根据具体情况进行合理的选择。只有在函数调用开销很大且频繁调用的情况下,才适合使用内联函数来提高程序的执行效率。
宏的优缺点:
优点: 1.增强代码的复用性。
2.提高性能。
缺点: 1.不方便调试宏。(因为预编译阶段进行了替换)
2.导致代码可读性差,可维护性差,容易误用。
3.auto
auto
是C++11引入的一个关键字,用于自动推导变量的类型。使用auto
关键字声明变量时,编译器会根据初始化表达式的类型推导出变量的类型。
auto
的主要优点是简化代码,减少冗余的类型声明。使用auto
可以让编译器根据初始化表达式的类型自动推导出变量的类型,避免手动指定类型的繁琐过程。
auto x = 5; // 推导为int类型
auto y = 3.14; // 推导为double类型
auto z = "hello"; // 推导为const char*类型
需要注意的是,auto
并不是完全代替了显式类型声明,在某些情况下仍然需要显式指定变量类型,例如函数参数、函数返回值、泛型编程等。此外,由于auto
是在编译时进行类型推导,因此在运行时无法改变推导出的变量类型。
总之,auto
关键字提供了一种简化代码的方式,通过自动推导变量类型减少冗余的类型声明,使代码更加简洁和易读。需要注意的是auto不能作为函数参数,也不能用来定义数组。
不能作为函数参数:函数参数需要在函数声明时确定其类型,以便在函数调用时进行类型匹配。而auto
用于自动推导变量类型,是在初始化时通过变量的初始值来确定类型的。由于函数参数在函数声明时并没有初始值可供推导,因此无法使用auto
来声明函数参数。
不能用来定义数组:数组的大小和元素类型需要在编译时确定,而auto
关键字是用于在编译时根据初始化表达式自动推导变量的类型。
typedef char* pstring;
int main()
{
const pstring p1; // 编译成功还是失败?
const pstring* p2; // 编译成功还是失败?
return 0;
}
-
const pstring p1; 编译失败,因为const修饰的指针p1必须被初始化,而此处未进行初始化。
-
const pstring* p2; 编译成功,因为p2是一个指向const pstring类型的指针,没有要求必须初始化。
auto与指针和引用结合起来使用:
用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&
int main()
{
int x = 10;
auto a = &x;
auto* b = &x;
auto& c = x;
cout << typeid(a).name() << endl;
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
*a = 20;
*b = 30;
c = 40;
return 0;
}
这里的typeid().name()还帮助我们了解参数类型的函数,头文件是#include<typeinfo>.
![](https://i-blog.csdnimg.cn/direct/5d1c7ee6dea747348b76c13afe14a8fa.png)