代码段1:

#include<iostream>
using namespace std;

class C{
public:
    C(){}
    C(const C& c){
        cout<<"const copy constructor called"<<endl;
    }
};
int main(){
    C c1;
    C c2 = c1;
    return 0;
}

输出:调用const复制构造函数

片段2:
#include<iostream>
using namespace std;

class C{
public:
    C(){}
    C(const C& c){
        cout<<"const copy constructor called"<<endl;
    }
    C(C& c){
        cout<<"non-const copy constructor called.\t "<<endl;
    }
};
int main(){
    C c1;
    C c2 = c1;
    return 0;
}

输出:称为非常量复制构造函数

片段3:
#include<iostream>
using namespace std;

class C{
public:
    C(){}
    C(const C& c){
        cout<<"const copy constructor called"<<endl;
    }
    C(C c){
        cout<<"non-const copy constructor called.\t "<<endl;
    }
};
int main(){
    C c1;
    C c2 = c1;
    return 0;
}

输出:错误:复制构造函数必须通过引用传递其第一个参数

我很困惑:

片段2的
  • 为什么这里的非const复制构造函数有效?为什么要调用非const复制构造函数,而不是const一个。
  • 片段3的
  • ,我知道复制构造函数必须使用const引用以避免无限递归。但是这里C类有C(const C& c)C(C c)不会引起无限递归,为什么它仍然不起作用?
  • 最佳答案

    代码段1 :一个带有const T&的标准拷贝构造函数。快乐的世界。

    代码段2 :

    有效完成的工作是使复制构造函数过载-一个使用引用T&的拷贝构造函数,而另一个使用一个恒定引用const T&的拷贝构造函数。

    请注意:类T的任何构造函数具有一个必需的T &const T &类型的参数(它可能还具有其他默认参数)是复制构造函数。

    因此,对于编译器而言,一切都归结为找到用于过载解析的最适合,它的完成方式是:



    所以写

    C c1;
    C c2 = c1;
    

    会调用非const复制构造函数,因为它是更好的匹配,但是,

    写作,
    const C c1;
    C c2 = c1;
    

    将调用const复制构造函数(您可以检查),因为现在带有const的复制构造函数是唯一可行的匹配项。

    片段3对于编译器来说是完全错误的。
    C(C c){
            cout<<"non-const copy constructor called.\t "<<endl;
        }
    

    您不能使用带有签名C(C c)的方法。编译器认为您正在尝试编写一个拷贝构造函数而错过了写&的操作,因此报告了错误。删除它,它工作正常。

    @除非您有充分的理由,否则永远不要将C(C& c)用作拷贝构造函数。不要跳过const ,因为对从中进行复制的对象进行更改没有多大意义。

    08-17 05:22
    查看更多