作者:大漠刀客
链接:https://www.nowcoder.com/discuss/29421
来源:牛客网
下面代码中的HasPtr hp4 = HasPtr(1,str);
这里有用到拷贝构造函数,拷贝构造函数中的语句“调用拷贝构造函数”
并没有输出。
但是将拷贝构造函数中的const去掉变成HasPtr( HasPtr& hp)又报错了,
拷贝构造函数中的第一个参数必须是引用类型,但未必是const吧?
而且从正确使用时的输出看,这里拷贝构造函数HasPtr( const HasPtr& hp)并没有调用啊
#include <iostream>
#include <memory>
using std::string;
using std::cout;
using std::endl;
class HasPtr{
public:
HasPtr() = default;
HasPtr( int i1,string &str ){
i = i1;
ps = &str;
}
HasPtr( const HasPtr& hp){
i = hp.i;
ps = new string( *hp.ps );
cout<<"调用拷贝构造函数"<<endl;
}
int i;
string *ps;
};
int main( ){
string str = "hello";
HasPtr hp4 = HasPtr(1,str);
cout<<hp4.i<<" "<<hp4.ps<<endl;
return 0;
}
拷贝构造被调用的三个条件
1.对象拷贝(A a;B b(a))
2.对象作为参数传值
3.对象作为函数返回值被赋值给左值
对于HasPtr hp4 = HasPtr(1,str);
来说,一般来讲应该是表达式右端先生成一个临时对象,然后调用拷贝构造函数初始化hp4.
但是这其中的临时对象其实是多余的,所以编译器就将这种形式的表达式优化成了HasPtr hp4(1, str);
,也就是跳过了临时对象的
创建过程,节省了调用一次拷贝构造函数的消耗。
至于拷贝构造函数中使用非const引用导致报错,这是因为HasPtr hp4 = HasPtr(1,str);
中HasPtr(1,str)是右值,非const的左值
无法绑定到右值上,可以使用右值引用或者const引用(直接按值传递也可以,但是在此例中不行,会导致无穷递归)。