C++拷贝构造函数形参必须定义为const 引用类型的情况
以下代码拷贝构造函数的形参必须为const 引用类型。
测试代码:
#include <iostream>
using namespace std;
class cat
{
public:
cat(int intialAge=0) :
catAge(intialAge)
{
cout << "cat cons" << endl;
}
cat(cat& t) :
catAge(t.catAge)
{
cout << "cat copy" << endl;
}
~cat() { cout << "cat des" << endl; }
private:
int catAge;
};
class dog
{
public:
dog(int intialAge) :
dogAge(intialAge)
{
cout << "dog cons" << endl;
}
dog(dog& t) :
dogAge(t.dogAge)
{
cout << "dog copy" << endl;
}
~dog() {
cout << "dog des" << endl;
}
private:
int dogAge;
};
class zoo {
public:
zoo(cat a, dog b, int t) :
zooDog(b), zooAge(t),zooCat(a)//成员初始化顺序与类中定义顺序一致
{
cout << "zoo con" << endl;
}
zoo(zoo& zoot) :zooCat(zoot.zooCat), zooDog(zoot.zooDog), zooAge(zoot.zooAge)
{
cout << "zoo copy" << endl;
}
~zoo() { cout << "zoo des" << endl; }
private:
cat zooCat;
dog zooDog;
int zooAge;
};
cat outPut(cat cat1) {
cout << 1 << endl;
return cat1;
}
dog outPut(dog dog1) {
cout << 2 << endl;
return dog1;
}
int main()
{
cat cat1(1);
dog dog1(4);
cout<<endl;
zoo zoo1(outPut(cat1), outPut(dog1), 6);
system("pause");
return 0;
}
原因分析:
初步猜测
可能是函数调用过程中返回了const的类型导致拷贝构造函数不能接收出现编译报错:
没有匹配的函数。
查阅了两天资料后
精简后的测试代码:
#include <iostream>
using namespace std;
class cat
{
public:
cat(int intialAge = 0) : catAge(intialAge){
cout << "cat cons" << endl;
}
cat(cat& t) : catAge(t.catAge) {
cout << "cat copy" << endl;
}
~cat() { cout << "cat des" << endl; }
private:
int catAge;
};
cat outPut(cat cat1) {
cout << 1 << endl;
return cat1;
}
int main()
{
cat cat1(1);
cout << endl;
outPut(outPut(cat1));
system("pause");
return 0;
}
解决方案:
1、自定义移动构造函数
#include <iostream>
using namespace std;
class cat
{
public:
cat(int intialAge = 0) : catAge(intialAge){
cout << "cat cons" << endl;
}
cat(cat& t) : catAge(t.catAge) {
cout << "cat copy" << endl;
}
cat(cat&& t) : catAge(t.catAge) {
cout << "cat copy" << endl;
}
~cat() { cout << "cat des" << endl; }
private:
int catAge;
};
cat outPut(cat cat1) {
cout << 1 << endl;
return cat1;
}
int main()
{
cat cat1(1);
cout << endl;
outPut(outPut(cat1));
system("pause");
return 0;
}
2、将复制构造函数形参声明为const的引用
#include <iostream>
using namespace std;
class cat
{
public:
cat(int intialAge = 0) : catAge(intialAge){
cout << "cat cons" << endl;
}
cat(const cat& t) : catAge(t.catAge) {
cout << "cat copy" << endl;
}
~cat() { cout << "cat des" << endl; }
private:
int catAge;
};
cat outPut(cat cat1) {
cout << 1 << endl;
return cat1;
}
int main()
{
cat cat1(1);
cout << endl;
outPut(outPut(cat1));
system("pause");
return 0;
}
原因分析:
C++ Primer(5th) 202页 引用返回左值一讲中提到:
函数的返回类型决定函数调用是否是左值。调用一个返回引用的函数得到左值,其他返回类型得到右值,可以像使用其他左值那样来使用返回引用的函数的调用,特别是,我们能为返回类型是非常量引用的函数的结果赋值。
暂时还没有弄清楚为什么函数返回是右值,在这里不妨假设这个右值就是const cat类型的;
当复制构造函数形参为cat&,即为左值引用cat类型,故不能将一个右值赋值给左值引用类型,可用如下代码表示该错误。
const cat& cat5(5);
cat& cat1 = cat5;
解决方案一原因分析:
移动构造函数形参为cat&&,是一个右值引用,可以接收返回类型为右值的参数。
即相当于:
const cat cat5(5);
cat&& cat1 = const cat cat5;
解决方案二原因分析:
复制构造函数形参为const cat&,是一个左值常量引用,可以用右值对其初始化。
const cat cat5(5);
const cat& cat1 = const cat cat5;
总结
当调用的函数返回一个非引用类型的对象时,返回值为右值,此时若想直接用该对象拷贝初始化令一个对象,则需要
1.将复制构造函数形参列表定义为常量类型
或者
2.自定义移动构造函数