C++ 为什么调用复制构造函数

C++ 为什么调用复制构造函数,c++,constructor,operator-keyword,C++,Constructor,Operator Keyword,我无法理解为什么调用复制构造函数而不是编译错误 我声明了两个类A和B,它们是独立的。A不是B的基础/派生。它们之间的唯一联系是,在B中,我使用一个将B转换为A的运算符 我已经定义了一个操作符=作为参数获取一个常量引用B。 大体上,我已经编写了以下B=A实例的说明。我希望会生成一个编译错误。但是操作符=被调用 class A {}; class B { public: // conversion from A (constructor): B() { c

我无法理解为什么调用复制构造函数而不是编译错误

我声明了两个类A和B,它们是独立的。A不是B的基础/派生。它们之间的唯一联系是,在B中,我使用一个将B转换为A的运算符 我已经定义了一个操作符=作为参数获取一个常量引用B。 大体上,我已经编写了以下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;
}
A类{};
B类{
公众:
//从(构造函数)转换:
B()
{

cout您拥有的不是复制构造函数,而是转换构造函数。之所以调用转换构造函数,是因为您可以将
a
转换为
B

这样做:

explicit B(const A& x)
现在,您将禁止从
A
B
的隐式转换

当您这样做时:

bar = foo;
编译器寻找合理的操作,最多允许一次转换。它可以使用
B
中的复制赋值,并且知道它可以从
a
中创建
B
(因为构造函数不是显式的),所以它以静默方式执行此操作


正如@lubgr所说,clangtidy有一个规则来检查这些,这就是。

您有一个隐式构造函数

B::B(const A&)
它执行您不希望的转换。您可以将签名更改为

explicit B(const A&);
触发编译错误。请注意,在默认情况下,最好使用一个参数
explicit
标记构造函数(它也有一个
clangtidy
),以避免意外地进行此类转换(IMHO,如果可以使用单个参数构造的构造函数在默认情况下是
显式的
,并且能够使


我预计将生成以下编译错误

no match for 'operator=' ... note: no known conversion for argument 1 from 'A' to 'const B&'
没有理由期望出现这种错误,因为存在从
a
常量B的已知转换&
B
具有
a
的转换构造函数:


它们之间唯一的联系是,在B中,我使用一个将B转换为A的运算符

…它们之间的第二个联系是,在
B
中,使用构造函数将
a
转换为
B


您认为这是一个转换cunstroctor,这是对的。但是为什么在赋值bar=foo发生时调用它呢

因为赋值的给定操作数的类型为
A
,而声明的参数类型为
常量B&


如果参数类型与声明不匹配,编译器将检查是否存在可用于转换参数的隐式转换序列。因为,
A
隐式转换为
B
,这样的隐式转换序列存在并将被使用。

我不清楚您为什么认为e应该生成错误。什么类型的错误?您认为程序有什么问题?我预计将生成以下编译错误39:6:错误:“运算符=”(操作数类型为“B”和“A”)不匹配39:6:注意:候选项为:23:5:注意:B&B::运算符=(常量B&)23:5:注意:没有已知的参数1从'A'到'const B&'的转换,您是对的,这是一个转换cunstroctor。但是为什么在赋值bar=foo发生时调用它。这就是我用正在发生的事情来更新我的答案的原因。
B(const A& x)