摘要: 技术在于交流、沟通,转载请注明出处并保持作品的完整性。
一 Reference
引用:之前提及过,他的主要作用就是取别名,与指针很相似,实现也是基于指针.
1.引用必须有初值,且不能引用nullptr
2.引用之后不能再引用别人
3.引用通常不用于声明变量,多用于参数类型,和返回值类型
见下面代码
int main(int argc, const char * argv[]) { int x=0; //p is a pointer to x int* p = &x; // r is a reference to x int& r = x; //这个操作并不是r引用了别人而是 是r引用的x = 5 int x2 = 5; r = x2; // x = 5 cout << "x = "<< sizeof(x) << endl; cout << "r = "<< sizeof(r) << endl; cout << "r的地址 = "<< &r <<endl; cout << "p的地址 = "<< p <<endl; return 0; }
输出结果
你会发现 r的地址个p的地址是相同的,其实引用并没有实际的内存,为了实现引用的取别名的假象,编译器会这么做 sizeof(r) = sizeof(x)和 &x = &r
4.引用是指针,是一种漂亮的指针
void func2 (string* obj) { obj ->clear();} //pass by pointer void func1 (string obj) { obj .clear();} //pass by value void func3 (string& obj) { obj .clear();} //pass by reference
调用端
string a; //pass by pointer 接口不同 func2(&a); //pass by value 调用接口相同 效率低 func1(a); //pass by reference 调用接口相同 func3(a);
5.不能用引用区分函数签名
double imag(const double& im) {return im;}; double imag(const double im) {return im;};
调用的时候你会发现
错误提示是函数调用混淆,你会发现不能用引用区分函数签名(上面红色部分为函数签名)
const也算函数签名的一部分
二 多态
带vaiturl 内存上会多一个4字节的指针
继承是继承调用权 而不是继承内存大小
动态绑定的三个前提
1.必须通过指针调用
2.指针为向上的关系(保证安全)
3.调用的是虚函数
(*(p->vptr)[n])(p));
(*p->vptr[n])(p)
三 const
a.const object(data member不得改变)
b.non-const object(data member可以改变)
c.const member function(保证不改变data member)
d.non-const member functions(不保证 data member不变)
他们的组合关系
当成员函数的const 和non-const版本同时存在,const object 只会调用const 版本,non-const object 只会调用non-const
我们思考一下
const String str("Hello world"); str.print();
如果print()不加const[const object与non-const member function] 会报错
Copy On Write,带const 不用考虑 COW
class template std::basic_string<...> //里面有两个member function charT operator[] (size_type pos) const {不考虑COW == Copy On Write}; reference operator[](size_type pos){必须考虑COW};
四 New 和 Delete
之前提过
new = malloc() + ctor
delete = dtor + free()
new 和delete不可以重载 但是 operator new 和 operator delete可以重载
class Foo { public: Foo() { cout<< "Foo ("<< ++ctorNum << ")"<<endl; } ~Foo() { cout<< "~Foo ("<< ++dtorNum << ")"<<endl; } //重载成员operatpr new void* operator new(size_t size) noexcept { cout<< "Foo operator new" <<endl; return malloc(size); } //重载成员operatpr delete void operator delete(void* ptr, size_t size) { cout<< "Foo operator delete" <<endl; free(ptr); }}
调用端
int main() { Foo * p = new Foo; delete p; }
结果
发现我们接管了 operator new 和operator delete
class Foo { public: Foo() { cout<< "Foo ("<< ++ctorNum << ")"<<endl; } ~Foo() { cout<< "~Foo ("<< ++dtorNum << ")"<<endl; } //重载成员operatpr new void* operator new[](size_t size) { cout<< "Foo operator new" <<endl; return malloc(size); } //重载成员operatpr delete[] void operator delete[](void* ptr, size_t size) { cout<< "Foo operator delete[]"<<endl; cout << size <<endl; free(ptr); } static int ctorNum; static int dtorNum; }; int Foo::ctorNum = 0; int Foo::dtorNum = 0;
调用端
int main() { Foo* l = new Foo[5]; delete[] l; return 0; }
结果
我们可以重载多个版本的class menber operator new() 第一参数必须为 size_t
我们可以重载 class member operator delete() 可以重载过个版本 ,但是他们绝对不会被delete
调用重载的delete()只有当new所调用的ctor抛出 exception 才会调用这些重载版的operator delete() 它只可能这样被调用,主要用归还未能完全城建成功的object所占用的 内存
调用会一一对应 ,如果你的delete()与new() 没有一一对应编译器 也不会报错 表示放弃对异常做处理放弃
class Bad{};//抛出异常用 class test { public: test(){} test(int i){/*故意抛出异常*/ throw Bad();} ~test(){} //一般的operator new() void* operator new(size_t size){cout<< "一般的operator new()" <<endl; return malloc(size);} //一般的operatpr delete void operator delete(void* ptr, size_t size){cout<< "一般的operator delete()"<<endl; free(ptr);} //标准库的operator new() void* operator new(size_t size, void* start){cout<< "标准库的operator new()" <<endl; return start;} //标准库的operator delete() void operator delete(void*, void*){cout<< "标准库operator delete(void*, void*)" <<endl;} //崭新的operator new() void* operator new(size_t size, long extra){cout<< "崭新operator new()" <<endl; return malloc(size + extra);} //崭新的operator new() void operator delete(void*, long){cout<< "崭新operator delete(void*, long)" <<endl;} //又一个operator new() void* operator new(size_t size, long extra, char init){cout<< "又一个operator new()" <<endl; return malloc(size + extra);} //又一个operator delete() void operator delete(void* size, long extra, char init){cout<< "又一个operator delete()" <<endl;} };
调用及输出
int main() { try{ test t; test* p1 = new test; test* p2 = new (&t) test; test* p3 = new(100) test; test* p4 = new(100,‘a‘) test; test* p5 = new(100) test(1); test* p6 = new(100,‘a‘) test(1); test* p7 = new(&t) test(1); } catch(...){}; return 0; }
发现new和delete是一一对应,至于其他的为什么没有打印出来是由于,new不成功抛出异常导致
完!
参照<<侯捷 C++面向对象高级编程>>