【菜鸟C++学习笔记】23. 对象的传递机制

来源:互联网 发布:linux打开命令行窗口 编辑:程序博客网 时间:2024/04/28 17:48

上次说的三种参数传递方式,对于一个数据来说没太大的差别,要是换做是一个具有n个数据成员的对象,那在内存中就需要建立n个副本,这种开销就大了去了,另外的原因如下:

1、对象的传递

对象作为参数传递一次,就需要调用复制构造函数,为对象在内存中创立一个副本,生命结束后,又需要调用析构函数销毁对象,例如:

#include <iostream>using namespace std;class A{public:A(){cout<<"构造函数执行创立对象"<<endl;}~A(){cout<<"析构函数执行销毁对象"<<endl;}A(A&){cout<<"复制构造函数执行创立对象副本"<<endl;}};A fun(A a){return a;}int main(){A a;fun(a);return 0;}

输出结果:


分析:

1)当创建一个对象a时,调用复制构造函数A()

2)函数fun(a)把对象a作为参数传递给fun函数时,由于是按值传递,会调用复制构造函数创建一个副本

3)函数fun中把a对象a返回时又传递了一次,因此又调用复制构造函数创建第二个副本

4)由于以上加起来在内存中创建了3个同样的对象a,因此调用3次析构函数销毁对象。

 

2、按地址和引用传递对象

方法很简单,把主函数中fun()的参数改为“&a”,在fun函数定义的开头将函数的接收参数和返回参数都设为指针,即加“*”,即为按地址传递;

把fun函数定义的开头将函数的接收参数和返回参数都设为引用型,即加“&”,其他结构不变,即为按引用传递;

输出结果:


分析:

可见对于按地址传递和按引用传递的机制来说,对象本身的值并没有传递,因此没有调用复制构造函数,为系统节约了一大笔开销。

讨论:对于按地址传递,我们可以把接收参数、返回参数和指向参数的指针都设为const值,起到保护作用,即第10行代码替换为:

const A *const fun(A *const a)

这样保证了函数接受和返回的对象都是不可修改的,同时指向返回值的指针也是不可修改的。 


3、指针和引用的区别

1)指针可以为空,引用不能为空

2)指针可以被赋值,引用只能被初始化

3)在堆中创建内存区域时必须用指针来指向它,但可以为该指针取一个外号

4)指针和引用可以混合使用,比如下面这个蛋疼的代码:

int *&p=new int

实际的指针就是&p,只不过p本身又是指针的一个外号而已。