[英]Why the copy constructor is called
我无法理解为什么调用拷贝构造函数而不是编译错误。
我声明了两个AB类,它们是独立的。 A不是基于B的/派生的。它们之间的唯一联系是,在BI中,使用将B转换为AI的运算符定义了一个operator =,该运算符将B的const引用作为参数。在主体中,我编写了以下示例B = A的实例。我希望会产生编译错误。 但是运算符=被称为
class A {};
class B {
public:
// conversion from A (constructor):
B()
{
cout << "1." << endl;
}
B(const A& x)
{
cout << "4." << endl;
}
// conversion from A (assignment):
B& operator= (const B& x)
{
cout << "3." << endl;
return *this;
}
// conversion to A (type-cast operator)
operator A() {
cout << "2." << endl;
return A();
}
};
int main()
{
A foo;
B bar; // calls constructor
bar = foo; // calls assignment
//foo = bar; // calls type-cast operator
char c;
c = getchar();
return 0;
}
我期望编译错误。 但是,将按以下顺序打印1 4 3。 我几乎不理解副本构造函数的调用方式以及为什么operator =不会产生问题
谢谢
它不是您拥有的副本构造函数,而是转换构造函数。 之所以调用转换构造函数,是因为您可以将A
变成B
做这个:
explicit B(const A& x)
现在,您将禁止从A
到B
的隐式转换。
当您这样做时:
bar = foo;
编译器寻找合理的操作,最多允许一次转换。 它可以使用拷贝赋值从B
,并且知道它可以创建一个B
出的A
(因为构造不明确),所以它这样做默默。
正如@lubgr所说,clang-tidy有一个检查这些规则的规则,这是C ++核心准则的一部分 。
您有一个隐式构造函数
B::B(const A&)
执行不需要的转换。 您可以将签名更改为
explicit B(const A&);
触发编译错误。 请注意,优良作法是在构造函数中默认使用一个explicit
标明的参数(也有对其clang-tidy
检查 ),只是为了避免偶然地进行此类转换(恕我直言,如果可以使用默认情况下,单个参数是explicit
的,并具有隐式的功能)。
我预计会生成以下编译错误
no match for 'operator=' ... note: no known conversion for argument 1 from 'A' to 'const B&'
没有理由预期这样的误差,这是因为从一个已知的转换A
到const B&
B
具有A
的转换构造函数:
B(const A& x)
它们之间的唯一联系是在BI中使用将B转换为A的运算符
...和它们之间的第二个联系是在B
,您使用了一个将A
转换为B
的构造函数。
您是对的,这是一个转换指导员。 但是为什么在分配bar = foo发生时调用此方法。
因为赋值的给定操作数的类型为A
,而声明的参数类型为const B&
。
在参数类型与声明不匹配的情况下,编译器将检查是否存在可用于转换参数的隐式转换序列 。 由于A
可以隐式转换为B
,因此存在并且将使用这种隐式转换序列。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.