为什么在分配发生时调用参数化构造函数?

Why Paramaterized constructor called when assignment is happening?

我的问题是针对最后一个陈述,即 return 0;

之前

为什么在我们尝试将 int 值分配给对象时调用 parametrize 构造函数。

我的一段代码:

#include<iostream>
using namespace std;
class Test {
private:
    int i;
    public:
    Test(int s=0):i(s) {
            cout<<"param ctor: "<<i<<endl;
    }
};

int main()
{
    Test a;         //param ctor called
    Test b(5);      //param ctor called
    //b(a);         //error as we have not implemented copy ctor
    b=a;            //compiler provided assignment opr. called
    b=100;          //why param ctor called for this.??
    return 0;
}

输出:

  param ctor: 0
  param ctor: 5
  param ctor: 100

我不确定,但是,

我开始知道编译器首先搜索匹配的函数调用..

b=100;

overloaded assignment operator function for class A 以 int 作为参数 当它找不到任何合适的匹配项时,它会直接调用参数化构造函数。

它依次完成剩余的分配工作。

如果我错了或遗漏了任何细节,请随时纠正我。

原因很简单:everyclassX有一个拷贝构造函数(一个取X的构造函数)和一个拷贝赋值运算符(取 X 的赋值运算符)。如果您不自己声明这些,编译器会隐式地为您声明它们。在某些情况下,它们被定义为已删除(这意味着使用它们是错误的),但它们始终存在。

所以当你这样做时:

b = 100;

有效翻译为:

b.operator=(100)

并搜索 operator= 的最佳匹配重载。实际上只有一个重载:隐式声明的复制赋值运算符 Test& Test::operator=(const Test &),因此编译器会检查它是否可以将参数 100 转换为赋值运算符的参数类型 const Test &。事实证明它可以,多亏了转换构造函数 Test::Test(int),所以这就是最终调用的内容。

如果你想禁用这种行为,你可以将构造函数标记为explicit。这将防止它被用于隐式转换,例如将 100 转换为赋值运算符参数的类型。

您的构造函数 Test(int s=0) 可用作从 intTest 的转换运算符。当计算 b = 100 时,100 被转换为 Test,然后调用默认赋值运算符。

当您执行 b=100 时,基本上发生的是编译器生成 b.operator=(Test(100))

您看到的构造函数调用来自 Test(100)

如果您创建构造函数 explicit,则编译器无法使用构造函数将 int 值隐式转换为 Test 对象,您会得到一个错误。