- 同class 的 obj 互为friend
- 传参和返回尽可能引用
- 返回时若是是临时变量不能引用
- 加减乘除负号不能返回引用,正号能够
- 传递者(return, 实参) 无需知道 接受者(函数返回类型,形参)是否是接受的引用
- 尽可能const(类方法,传参等)
- 构造函数尽可能初始化赋值不要经过{}赋值
c3+=c2+=c1
从右往左,operator +=
若是返回值不是对象或其引用则不能连续- 操做符都是做用于左边
T pc = new T(a)
的操做c++
void* mem = operator new(sizeof(T))
(实际内部调用malloc(n))pc = static_cast<T*>(mem);
//转型pc->T:T(a)
//调用构造函数(定义成员,赋值)
delete pc
的操做数组
T::~T(pc)
//析构函数operator delete(pc)
//(实际内部调用free(pc)
new []
要和delete []
对应用函数
- 内存分配会16字节的倍数 (32位和64位都是?)
- 若是没有对应,好比
T *p = new T[3]; delete p
- 调用
delete p
会释放申请的动态内存,可是只会调用一次析构函数(图是有问题的应该是从下往上析构)- 调用
delete[] p
才会在释放动态内存后,正确的调用三次析构函数![]()
- 如上图,若是不是
new
的数组,会少了从上往下的第二个3内存
- 内存依次记录的是(16进制):
- 分配的内存大小+1(1表明分配出去的意思,由于分配的大小会是16的倍数,能够用这一位)
- 若是是数组会记录数组的大小
- 实际数据
- 同第一个
class Account {
public:
static double m_rate; // 声明,同时须要在外部定义(应该是编译器怕致使重复连接 )
static const int x = 2.1; // 常量能够,也能够用很是量的方式,可是不能在内外都赋予初始值
static constexpr double d = 1.0; // 编译器-O0时对于非int char等须要这么操做
static Account ac; //能够不在外部定义(在外部定义也OK)
Account ac; // 错误类类型成员只能是static
};
double Account::m_rate; //定义(必需要有这一步)
复制代码
- 模板致使代码膨胀
- 继承函数继承的是调用权
- 委托模式共用引用修改时能够 copy-on-write (string的实现也是cow)
- 成员函数同时存在const 和 non-const版本时,const obj 只能调用const的,non-const的只能调用non-const的
![]()
- 继承和组合构造从内而外,析构由外而内,继承的父类析构必须是
virtual
- 继承空心三角箭头头
- 组合实心菱形箭头尾
- 委托空心菱形箭头尾
- T转换函数 ex:
operator double() const {return xxx;}
把T->double- 同时可使用no-explict的构造函数 ex:
T(double x){}
double->T
Fraction f(3,5);
double d = 4.0+f; // 会先找operator(double, Fration),看看能不能把Fraction转换成double, 找 operator double()或者non-explict构造函数,可是共存可能会致使二义性
复制代码
pointer-like classspa
- 特殊的重载符号
operator ->
,重载后不会消耗掉->
;- 迭代器也是一种智能指针
function-like class指针
- 重载
operator ()
- 若是类型是依赖于模板参数的限定名,那么在它以前必须加
typename
,避免编译器在实例化时才知道,explain(T::c
不加的话并不知道这个是个嵌套类型仍是静态成员或者静态函数) 好比:
template <class T> void foo() {
T::iterator * iter; // 不加typename, 这一行多是个乘法运算多是个定义语句
// ...
}
复制代码
连接器相关: 咱们须要注意从库中导入文件的粒度问题:若是某个特定符号的定义是必须的,那么包含该符号定义的整个目标文件(一个库可能会有多个目标文件)都要被导入code
有默认值的会编译不经过(list模板参数有默认值) cdn
![]()
虚函数实例内存多一个虚指针的大小对象