摘录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;
}
输出:错误:复制构造函数必须通过引用传递其第一个参数
我很困惑:
C(const C& c)
,C(C c)
不会导致无限递归,为什么它仍然不起作用?答案 0 :(得分:8)
Snippet 1 :一个标T&
的标准副本构造函数。快乐的世界。
代码段2 :
您有效完成的工作是重载复制构造函数 - 一个引用引用const T&
而另一个引用常量引用T &
。
请注意:类T的任何构造函数都有一个类型为const T &
或C c1;
C c2 = c1;
的强制参数(它可能还有其他默认参数)是一个复制构造函数。
所以,对于编译器来说,这一切只是归结为找到最适合来进行重载解析,它完成如下:
标准转换序列S1是比转换序列更好的转换序列 标准转换序列S2 if:
- ....
- S1和S2是引用绑定(8.5.3),引用引用的类型除了顶级cv限定符之外是相同的类型, 并且S2引用的引用所引用的类型更多 cv-qualified比S1初始化的引用类型 指。
所以写作
const C c1;
C c2 = c1;
将调用非const复制构造函数,因为它是更好的匹配,但是,
写入,
C(C c){
cout<<"non-const copy constructor called.\t "<<endl;
}
将调用const复制构造函数(您可以检查),因为现在复制构造函数与const是唯一可行的匹配。
Snippet 3对于编译器来说是完全错误的。
C(C c)
您无法使用签名&
的方法。编译器认为您正在尝试编写复制构造函数并错过编写C(C& c)
并因此报告错误。删除它,它工作正常。
@除非你有充分的理由,从未使用const
作为你的拷贝构造函数。不要跳过import org.acra.ReportingInteractionMode;
import org.acra.annotation.ReportsCrashes;
@ReportsCrashes(formUri = "",
mode = ReportingInteractionMode.DIALOG,
mailTo = "xyz@gmail.com",
resDialogText = R.string.reporttous,
resDialogOkToast = R.string.OK,
formKey = "")
public class UILApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
ACRA.init(this);
}
}
,因为改变你制作副本的对象并没有多大意义。
答案 1 :(得分:3)
for snippet 2,为什么这里的非const复制构造函数有效?为什么调用非const复制构造函数,而不是const。
请考虑此问题的代码,但请在下面添加评论// (*)
:
int main(){
const C c1; // (*) <- See change here
C c2 = c1;
return 0;
}
这会调用const
复制版本。它实际上与作为构造函数的函数无关 - 如果函数有两个重载,一个接受引用,一个引用const
,那么将使用第一个调用非const对象,并且第二个const
个对象。
对于代码片段3,我知道复制构造函数必须使用const引用来避免无限递归。但是这里C类有C(const C&amp; c),C(C c)不会导致无限递归,为什么它仍然不起作用?
请考虑以下代码,并注意没有调用(main
的内容已被删除)。
#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(){
// Note that nothing is creating C instances at all.
return 0;
}
这会导致完全相同的错误 - 编译器只是拒绝使用此接口编译类,无论是否有某些东西试图调用它。
引用this question的答案“§12.8/ 3中的标准禁止它:
如果类X的构造函数的第一个参数是类型(可选择cv-qualified)X并且没有其他参数,或者所有其他参数都有默认参数,那么它的构造函数声明是错误的。
“