内联函数
除了直接在函数名前面加 inline
将成员函数放在类里面进行定义,编译器也可能将该函数当做内联函数进行对待
c++中,被const 修饰的变量———常量
具有宏替换的特性——〉在编译阶段进行替换的——〉会进行类型检测——〉安全性高
int main()
{
const int a = 5; // 编译期间,将所有带有a变量的都用5 进行替换 , 参与类型检测
//类似于宏替换,但宏常量是在预处理期间进行,所以不进行类型检测,不能调试
// 在c++中,const 可以取代宏常量,可以检测类型,因此安全性更好。
int* pa = (int *)&a;
*pa = 100; //此时a空间存放的是100;
cout << a << endl; //5 编译器在编译期间就已经将a用 5给替换了
cout << *pa << endl; //100 指针指向a 常量的那块空间,此时该空间已通过指针近存放了100
return 0;
}
如何证明此时编译器会用函数体里面的内容,把函数调用的位置替换掉?
// 内联函数:编译器会用函数体里面的内容,把函数调用的位置替换掉
inline int Add(int left, int right)
{
return left + right;
}
int main()
{
int a = 10;
int b = 20;
// 如何证明此时编译器会用函数体里面的内容,把函数调用的位置替换掉?
//如果替换了,反编译就看不到函数的调用过程,就在主函数中找不到call指令
// 反之,就没有替换
int ret = Add(a, b);
cout << ret << endl;
system("pause");
return 0;
}
由于是为了弥补宏定义的缺陷,所以内联函数是可以进行类型检测和调试的,
因此在debug 模式下,内联函数是没有进行替换的,方便调试,
在release模式下就会优化发布工程的,所以是直接替换,不存在call指令
内联函数具有文件作用域,所以定义和声明不能分开
auto
// auto定义的变量:在编译阶段,根据提供的初始化表达式实际类型,来确定变量的类型
// auto 在定义变量时,必须要对其进行初始化,否则编译器无法推测出变量的实际类型;
//auto 并非是一种"类型"的申明,而是一种"占位符"
int main()
{
auto a = 10;
auto b = 3.13;
// auto c; //未初始化 错误
cout << typeid(a).name() << endl; //int 查看a变量的类型
cout << typeid(b).name()<< endl; // double
return 0;
}
范围for循环
void TestFunc(int* array) // 此时数组传参变为指针,
{
/* 范围for不能使用
for(auto e : array) // 指针不能明确数组的范围大小
cout << e <<" " ;
cout <<endl;
*/
}
int main()
{
int array[] = {1,2,3,4,5,6} //范围必须明确
for(auto& e : array) // 加上引用&,让e 依次去引用array中的每个元素,可修改元素
e *= 2;
for(auto e : array) // 不加引用,e就是数组中的每一份元素的拷贝;
cout << e <<" " ;
cout <<endl;
}
nullptr
nullptr_t 空值指针类型
nullptr 空值指针 , c++11引入的新的关键字
void TestFunc(int a)
{
cout << "TestFunc(int a)" << endl;
}
void TestFunc(int* pa)
{
cout << "TestFunc(int* pa)" << endl;
}
int main()
{
int *p = nullptr;
TestFunc(0);
TestFunc(NULL); //NULL 实际上被当作0来处理;此时就无法找到对用的重载指针函数
TestFunc(nullptr); // c++11,提供了空值指针;
return 0;
}