
未加static的全局变量和函数是全局可见的,当同时编译多个文件时,文件之间的变量或者函数可能会有命名冲突的情况,可以使用static来隐藏,使得变量或函数只能在该文件可见。
static 关键字会使得它修饰的变量存储在静态存储区,在程序开始运行是就初始化,并且会一直存在直到程序结束,并且不会被再次初始化。
同样有上述的几种功能,对该成员函数or静态变量进行隐藏以及改变其生命周期,并且所有的对象共用一个静态成员函数或静态变量。另外静态内部类也是实现单例模式的一种方法,其优点在于外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化 INSTANCE,故而不占内存,只有当 getInstance() 方法第一次被调用时,才会去初始化 INSTANCE。
const 用来表示常量,即不允许他修饰的变量被修改,在进行参数传递的时候,也常常使用const修饰引用来传参,既保证了不复制参数,又防止对象被修改。
C++ 中还可以用 const 修饰成员函数和数据成员来达到封装的目的,不允许使用const修饰的成员函数来修改数据成员。
extern 是 C/C++ 语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用(只是声明,不分配内存)
与 extern 对应的关键字是 static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被 extern “C”修饰。
被extern "C"修饰的变量和函数是按照C语言方式编译和链接的
之所以要如此是因为编译器在将C++源代码编译成目标文件时,会将函数和变量的名称进行修饰,形成符号名,目标文件中所使用的符号名就是修饰后名称,所以对于不同函数签名的函数,即使函数名相同,编译器和链接器都认为它们是不同的函数(重载)。因此有时候在调用一些库函数的时候,会出现无法链接的情况(因为函数签名不同)所以对于C++来说,必须使用extern "C"来声明这些函数。
RTTI是运行时类型检测,也是 C++11 的新特性,主要是在dynamic_cast、typeid中使用,在进行类型转换前或者获取类型时,会查询type_info指针来进行类型检测。
c++ 中的多态就是在父类的函数前加上 virtual 关键字,在子类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数,如果对象类型是子类,就调用子类的函数,如果对象类型是父类,就调用父类的函数。
多态的实现需要两个条件:
可以通过静态扫描来检测内存泄露,具体的操作为对象计数;重载 new/delete,记录分配点等
解决内存泄露可以使用智能指针,但要小心循环引用的问题。
auto实际上很早就被引入到 C++,用来进行类型推导,比如用在迭代器中。
传统的 C++ 无法区分 NULL 和 0,有的编译器会把 NULL 定义为 void*的指针,有的直接就定义为0了,这就会导致一系列的问题,比如在重载时会发生混乱,所以 C++11 引入了 nullptr 来区分空指针和0。
进行遍历的时候可以像python一样写auto iter:arr来遍历。
提供了统一的语法来初始化任意的对象,这两个特性就让人感觉 C++ 越来越智能而简洁了。
C++11 引入智能指针主要是因为C++没有自动的内存回收机制,所以当业务逻辑过于复杂的时候难免会出现内存没有 delete 的现象,这就容易造成内存泄漏的问题,智能指针主要就是被用来对这些资源进行动态管理,并及时释放无用的资源。
C++11 提供四种智能指针,有unique_ptr,shared_ptr, weak_ptr,以及auto_ptr,不过auto_ptr已经被弃用。
shared_ptr允许多个指针指向相同的对象,每次被引用就内部计数+1,析构则-1,当引用计数为0时则释放内存。unique_ptr只允许一个指针指向给定的对象,weak_ptr最大的作用在于协助shared_ptr,可以观测目标对象的引用计数。
智能指针会遇到的最大问题是循环引用,就像是类之间的循环引用一样,两个指针互相引用对方就会造成都无法析构的现象。循环引用的现象可以通过让引用链上的一方持用普通指针或弱智能指针 (weak_ptr) 来解决。
实现智能指针可以通过引入辅助类或者使用句柄。
辅助类实现即单独使用一个类来存储引用计数,每次在构造和析构智能指针类的时候对辅助类进行操作。
而句柄实现则是把指针封装起来,通过重载来重新定义指针的行为,将计数内置进去。
C++11 引入右值引用的目的是解决拷贝临时对象时的性能低下问题,在 C++11 之前,进行临时对象拷贝时会多调用一次构造函数并复制,这就使得性能低下。实际上直接移动变量的指向就会快得多,但 C++11 之前右值是不能被取地址的,所以没法进行右值引用。
从本质上来说,左值引实际上是用const 指针来实现的,它保存的是一个指向数据地址的指针,而如果进行反汇编可以发现右值引用是通过取地址来实现的,一个变量的右值引用存储的就是它的地址。
而对于传入的引用,在不知道是左值还是右值的情况下,可以用move函数来将其转换为右值,也就是实现了取地址的操作。
array 保存在栈内存中,相比堆内存中的 vector,速度更快,但 array 长度无法更改,没有 vector 灵活。
而新增了 tuple 感觉就是 C++ 在像 python 看齐