繁体   English   中英

为什么要调用复制构造函数

[英]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)

现在,您将禁止从AB的隐式转换。

当您这样做时:

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&' 

没有理由预期这样的误差,这因为从一个已知的转换Aconst 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM