摘要: 技术在于交流、沟通,转载请注明出处并保持作品的完整性。


一 Reference

引用:之前提及过,他的主要作用就是取别名,与指针很相似,实现也是基于指针.

1.引用必须有初值,且不能引用nullptr

2.引用之后不能再引用别人

3.引用通常不用于声明变量,多用于参数类型,和返回值类型

见下面代码

int main(int argc, const char * argv[]) {

    int x=;

    //p is a pointer to x
int* p = &x; // r is a reference to x
int& r = x; //这个操作并不是r引用了别人而是 是r引用的x = 5
int x2 = ;
r = x2; // x = 5 cout << "x = "<< sizeof(x) << endl;
cout << "r = "<< sizeof(r) << endl;
cout << "r的地址 = "<< &r <<endl;
cout << "p的地址 = "<< p <<endl;
return ;
}

输出结果

你会发现 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 = ;
int Foo::dtorNum = ;

调用端

int main()
{
Foo* l = new Foo[];
delete[] l;
return ;
}

结果

我们可以重载多个版本的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() test;
test* p4 = new(,'a') test;
test* p5 = new() test();
test* p6 = new(,'a') test();
test* p7 = new(&t) test();
}
catch(...){};
return ;
}

发现new和delete是一一对应,至于其他的为什么没有打印出来是由于,new不成功抛出异常导致

完!

参照<<侯捷 C++面向对象高级编程>>

C++面向对象高级编程(九)Reference与重载operator new和operator delete的更多相关文章

  1. C++面向对象高级编程(二)基础篇

    技术在于交流.沟通,转载请注明出处并保持作品的完整性. 概要 知识点1.重载成员函数 知识点2 . return by value, return by reference 知识点3 重载非成员函数 ...

  2. C++面向对象高级编程(一)基础篇

    技术在于交流.沟通,转载请注明出处并保持作品的完整性. 概要: 知识点1 构造函数与析构函数 知识点2 参数与返回值 知识点3 const 知识点4 函数重载(要与重写区分开) 知识点5 友元 先以C ...

  3. C++面向对象高级编程(七)point-like classes和function-like classes

    技术在于交流.沟通,转载请注明出处并保持作品的完整性. 1.pointer-like class 类设计成指针那样,可以当做指针来用,指针有两个常用操作符(*和->),所以我们必须重载这两个操作 ...

  4. C++面向对象高级编程(五)类与类之间的关系

    技术在于交流.沟通,转载请注明出处并保持作品的完整性. 本节主要介绍一下类与类之间的关系,也就是面向对象编程先介绍两个术语 Object Oriented Programming   OOP面向对象编 ...

  5. C++面向对象高级编程(八)模板

    技术在于交流.沟通,转载请注明出处并保持作品的完整性. 这节课主要讲模板的使用,之前我们谈到过函数模板与类模板 (C++面向对象高级编程(四)基础篇)这里不再说明 1.成员模板 成员模板:参数为tem ...

  6. C++面向对象高级编程(六)转换函数与non-explicit one argument ctor

    技术在于交流.沟通,转载请注明出处并保持作品的完整性. 1.conversion function 转换函数 //1.转换函数 //conversion function //只要你认为合理 你可以任 ...

  7. C++面向对象高级编程(四)基础篇

    技术在于交流.沟通,转载请注明出处并保持作品的完整性. 一.Static 二.模板类和模板函数 三.namespace 一.Static 静态成员是“类级别”的,也就是它和类的地位等同,而普通成员是“ ...

  8. C++面向对象高级编程(三)基础篇

    技术在于交流.沟通,转载请注明出处并保持作品的完整性. 概要 一.拷贝构造 二.拷贝赋值 三.重写操作符 四.生命周期 本节主要介绍 Big Three 即析构函数,拷贝构造函数,赋值拷贝函数,前面主 ...

  9. C++面向对象高级编程(上)-Geekband

    头文件和类声明 一定要注意使用防卫式的头文件声明: #ifndef _CLASSHEAD_ #define _CLASSHEAD_ . . . . #endif 基于对象和面向对象 : 基于对象 单一 ...

随机推荐

  1. SLAM for Dummies SLAM初学者教程 中文翻译 1到4章

    SLAM for Dummies  SLAM初学者教程A Tutorial Approach to Simultaneous Localization and Mapping  一本关于实时定位及绘图 ...

  2. POJ1845:Sumdiv(求因子和+逆元+质因子分解)好题

    题目链接:http://poj.org/problem?id=1845 定义: 满足a*k≡1 (mod p)的k值就是a关于p的乘法逆元. 为什么要有乘法逆元呢? 当我们要求(a/b) mod p的 ...

  3. 【转】Deep Learning(深度学习)学习笔记整理系列之(五)

    9.2.Sparse Coding稀疏编码 如果我们把输出必须和输入相等的限制放松,同时利用线性代数中基的概念,即O = a1*Φ1 + a2*Φ2+….+ an*Φn, Φi是基,ai是系数,我们可 ...

  4. #C++初学记录(并查集)

    并查集 题目 今天是伊格那丢的生日.他邀请了很多朋友.现在该吃晚饭了.伊格那丢想知道他至少需要多少张桌子.你必须注意到并不是所有的朋友都认识对方,而且所有的朋友都不想和陌生人待在一起.这个问题的一个重 ...

  5. java之类适配器

    类适配器 所谓类适配器,指的是适配器Adapter继承我们的被适配者Adaptee,并实现目标接口Target.由于Java中是单继承,所以这个适配器仅仅只能服务于所继承的被适配者Adaptee.代码 ...

  6. 关于Serializable的一个形象的例子

    一.知识预备 根据使用Serializable的使用场景,可以发现所涉及的场景都是跨进程的,就是要做的事情不是在一个java进程中完成的,我们都知道java进程是基于jvm跑起来的,而每一个被创建出来 ...

  7. MySQL从删库到跑路(二)——MySQL字符集与乱码解析

    作者:天山老妖S 链接:http://blog.51cto.com/9291927 一.字符集与编码 1.字符集简介 字符(Character)是各种文字和符号的总称,包括各国家文字.标点符号.图形符 ...

  8. Python通用网络爬虫脚本

    from sys import argv from os import makedirs,unlink,sep,mkdir from os.path import dirname,exists,isd ...

  9. Tomcat java.lang.OutOfMemoryError: PermGen space error

    Often time, Tomcat may hits the following java.lang.OutOfMemoryError: PermGen space error. java.lang ...

  10. SNMP学习笔记之SNMPWALK 命令

    SNMPWALK是一个通过SNMP GET-NEXT类型PDU,实现对目标AGENT的某指定MIB分支信息进行完整提取输出的命令工作. 命令行: snmpwalk [选项] agent [oid] 选 ...