0 概述
1 引用
1.1 左值、右值
注:当前看到的地方,后期补充其他内容。
近乎完美的swap
// 只能交换左值
tempate<class T>
void swap(T& a, T& b)
{
T tmp{move(a)};
a = move(b);
b = move(tmp);
}
该过程不执行拷贝操作,只进行移动操作。
move(x)并不是真正的移动x,只是为x创建了一个右值引用。
扩展swap功能:
// 增加重载函数
template<class T>
void swap(T&& a, T&b)
template<class T>
void swap(T& a, T&& b)
1.2 引用的应用
令引用指向某类型的引用,得到的还是该类型的引用,而非特殊的引用的引用类型。
using rr_i = int&&;
using lr_i = int&;
using rr_rr_i = rr_i&&; // int&& &&的类型是int&&
using lr_rr_i = rr_i&; // int&& &的类型是int&
using rr_lr_i = lr_i&&; // int& &&的类型是int&
using lr_lr_i = lr_i&; // int& &的类型是int&
综上,左值引用优先。上述现象称为引用合并(reference collapse)
C++不允许行为:
int&& &r = i; // 禁止行为,引用的引用只能作为别名
1.3 指针与引用
共同点:无需拷贝就可以在别处使用对象的机制。
如果需要更换所指向的对象,使用指针;
如果想要让某个名字永远对应同一个对象,应使用引用。
如果想要自定义(重载)一个运算符,使之用于指向对象的某物,应该使用引用。
C++不允许重定义指针等内置类型的运算符含义。
值空缺 -> 指针 nullptr,没有空引用
2 建议
【1】使用指针时越简单直接越好;
【2】不要对指针执行稀奇古怪的算术运算;
【3】注意不要越界访问数组,尤其不要在数组之外的区域写入内容;
【4】不要使用多维数组,用合适的容器替代;
【5】用nullptr代替0和NULL;
【6】与内置的C风格数组相比,优先选用容器(vector\array\valarray);
【7】优先选用string,而不是以0结尾的char数组;
【8】若字符串字面值常量中包含太多反斜线,则使用原始字符串;
【9】const引用比普通引用更适合作为函数的实参;
【10】只有当需要转发和移动时才使用右值引用;
【11】让表示所有权的指针位于句柄类的内部;
【12】在底层代码之外尽量不要使用void*;
【13】用const指针和const引用表示接口中不允许修改的部分;
【14】引用比指针更适合作为函数的实参,不过当需要处理“对象缺失”的情况时类外;