C++构造函数、拷贝构造函数、赋值运算符漫谈(一)——函数参数传递
来源:互联网 发布:水刀编程软件 编辑:程序博客网 时间:2024/04/30 20:09
在讨论C++函数参数之前,我们先来看一下C程序是如何调用函数的。
如图,为C语言的函数调用记录,C++也类似。当有如下函数:
void foo(X x0);
如果有如下调用方式:
X xx;
foo(xx);
编译器(对于C)会将实参xx以“位逐次拷贝”方式复制给形参x0(注:X0即在上图函数活动记录中的参数位置)。在C++中,如果一个Class也展现了“位逐次拷贝语义”【1】,且用户没有定义拷贝构造函数,那么编译器按照这种方式进行拷贝没有问题。但是当一个Class不展现“位逐次拷贝语义”的情况(四种),或者用户定义了拷贝构造函数呢?这种情况编译器必须采用一定措施避免这种直接位拷贝的发生(否则拷贝构造函数将不能发生作用)。C++编译器是这样做的:
调用函数前,先引入一个X的临时变量temp,并以实参xx为参数调用拷贝构造函数(这由编译器安插代码完成)。如:
X temp;(此处不调用构造函数,只分配空间)
temp.X::X(xx);(这两行代码是由编译器插入)
之后怎么办呢?如果直接foo(temp),问题又回到之前了,因为只是相当于temp变成了实参,实参到形参x0的拷贝依然是“位逐次拷贝”。所以C++编译器必须做第二个转化,即修改函数foo的声明,将其修改为:
void foo(X& x0);
即函数参数变为引用,传入的将是temp的地址。
测试:
点击(此处)折叠或打开
- class X
- {
- public:
- X()
- {cout<<"X()"<<endl;};
- X(const X& x)
- {
- cout<<"X(const X& x)"<<endl;
- }
- X& operator=(const X&)
- {
- cout<<"="<<endl;
- }
- ~X()
- {cout<<"destructor"<<endl;}
- };
- void foo(X x0)
- {
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- X xx;
- foo(xx);
- }
运行结果:
可以看出函数参数的传入需要调用拷贝构造函数构建一个临时对象(注:并不是构建形参,形参已经被转化为引用,不再是对象),另外临时对象在函数退出时销毁。
总结:函数形参中,对象值传递的方式都转化为临时对象和引用传递。
【1】一个类不展现“位逐次拷贝”的四种情况:
(1) 这个类有member object,并且这个member object对应的Class定义了拷贝构造函数。
(2) 这个类的父类定义了拷贝构造函数。
(3) 这个类中有虚函数(包括其父类有的情况)。
(4) 这个类的继承连中有虚基类。
本文章有上海android培训上海电脑培训机构推荐阅读
- C++构造函数、拷贝构造函数、赋值运算符漫谈(一)——函数参数传递
- C++构造函数、拷贝构造函数、赋值运算符漫谈(一)——函数参数传递
- C++构造函数、拷贝构造函数、赋值运算符漫谈(一)——函数参数传递
- C++构造函数、拷贝构造函数、赋值运算符漫谈(三)——NRV
- C++构造函数、拷贝构造函数、赋值运算符漫谈(三)——NRV
- C++构造函数、拷贝构造函数、赋值运算符漫谈(二)——函数返回值
- C++构造函数、拷贝构造函数、赋值运算符漫谈(二)——函数返回值
- C++构造函数、拷贝构造函数、赋值运算符漫谈(二)——函数返回值
- 默认构造函数,拷贝构造函数,拷贝赋值运算符
- 拷贝构造函数&构造函数&重载赋值运算符
- 拷贝构造函数&构造函数&重载赋值运算符
- 关于拷贝构造函数,赋值运算符
- 拷贝构造函数和赋值运算符
- 拷贝构造函数与赋值运算符
- 拷贝构造函数和赋值运算符
- 拷贝构造函数和赋值运算符
- 拷贝构造函数与赋值运算符
- 拷贝构造函数和赋值运算符
- Spring在javaweb工程中的简单配置与应用
- CSS3实现三角框
- c++输入输出格式 %i
- Elasticsearch——Templates 模板
- 你好啊
- C++构造函数、拷贝构造函数、赋值运算符漫谈(一)——函数参数传递
- 把Gps坐标转成百度坐标的java方法
- 程序员可以在周末做的8件事
- Hbase在数据统计中的应用心得
- Tomcat错误-Port already in use
- 在一个activity中添加多个listview
- 机器学习-朴素贝叶斯分类器
- 昔我往矣,杨柳依依
- 读取excel大于Z列的数据