目录
内联函数
常规函数的调用,会使程序跳转到函数地址,函数结束时返回。将函数指定为内联函数,编译器会在调用内联函数的位置展开,避免了函数调用的开销,为此要占用更多内存,使目标文件变大,例如调用了10次内联函数,则该程序内联函数展开了10次,该程序就带有了内联函数的10个副本,倘若用常规函数,则只有一个副本。
因为内联函数节省的是函数调用时的开销,倘若内联函数规模大,则节省的时间微乎其微,编译器也不再当作内联函数处理,或者是内联函数中含有递归,也不再被作为内联函数,即内联函数声明是向编译器发出的请求,编译器可以不理睬。可见内联函数适用于规模小,流程直接,被频繁调用的函数。
内联函数传递参数也是值传递参数,如果参数是表达式,将传递表达式的值,这点上,宏就做不到了,因为参数是表达式,宏是通过文本替换实现的,多次执行表达式,可能会有副作用。
将函数定义或声明前加上inline,向编译器说明这是一个内联函数,内联函数定义和声明应当不分离,否则内联函数被展开后,将找不到函数地址,链接时错误。内联函数可以在头文件声明和定义,或者在头文件声明,在使用的地方定义,事实上这两种做法做法等价,因为前后者使用的地方都引用了头文件,总之,定义与声明不能分离。
例如:(定义与声明分离,链接错误)
例如:
如果把代码这样写
int main()
{
//int a=f(100);
int a;
{
int i = 100;
++i;
a = i;
}///等价的代码
return 0;
}
调试,查看汇编代码,发现一模一样,原来编译器展开内联函数做了这么个事。
auto关键字
在c早期,auto 关键字是修饰局部变量的关键字很少使用。
c++11给予auto新含义:auto作为类型说明符来指示编译器分析表达式的类型,auto声明的变量必须由编译器在编译时期推导而得,所以auto定义的变量需要有初始值,故auto不能做形参类型,当类型名很长时,用auto自动推导类型能简化代码。(auto也不能定义数组)
auto一般会忽略顶层const,保留底层const。(注:顶层const指对象是常量,底层const指指针指向的对象是常量)
例如:
const int a=0;
auto b=a;//b是一个整形变量(忽略顶层const)
auto c=&a;//c是一个指向整形常量的指针(保留底层const)
希望推导出顶层const,需明确指出 const auto bb=a;
设置类型为auto的引用,以引用对象的类型作为auto的类型:
auto &d=a//d是整形常量引用,是a的别名
auto &e=100;//错误,auto推导e的类型是int&,e是非常量引用,引用了字面值常量
const auto &f=100//正确,f是常量引用,(const int temp=100,const int &f=temp等价)
用auto *推导指针变量的类型,不能推导非指针变量,例如:
auto可以连续推导,但是类型需一样。例如:
范围for
c++11提供的语句,可以遍历给定序列的每个元素并对序列的每个值执行操作。
格式:
for(变量:对象)
语句
例如遍历数组和遍历并修改数组元素:
写代码:
按c++11标准编译:
输出:
nullptr
在C++中NULL被定义为了0,在一些场景下可能有误解,例如NULL作为实参会被当成int类型,而不是我们想要的指针类型,在函数重载场景下可能会调用错函数。
C++11引入了新关键字nullptr,nullptr与(void*)0大小一致。 例如在64位平台下: