C++默认构造函数

ap2*_*014 3 c++ constructor

我使用以下代码得到编译错误:

main.cpp: In function âint main()â:
main.cpp:38: error: no matching function for call to âComplex::Complex(Complex)â
main.cpp:22: note: candidates are: Complex::Complex(Complex&)
main.cpp:15: note:                 Complex::Complex(double, double)
Run Code Online (Sandbox Code Playgroud)

但是当我将复制构造函数的参数类型更改为const Complex&时,它可以工作.我认为默认构造函数将使用2 Complex :: Complex(2.0,0.0)调用,然后将调用复制构造函数来创建一个带有Complex(2.0.0)的副本.不正确吗?

#include <iostream>
using namespace std;

class Complex {
        double re;
        double im;

public:
        Complex(double re=0, double im=0);
        Complex(Complex& c);
        ~Complex() {};
        void print();
};

Complex::Complex(double re, double im)
{
        cout << "Constructor called with " << re << " " << im << endl;
        this->re = re;
        this->im = im;
}

Complex::Complex(Complex &c)
{
        cout << "Copy constructor called " << endl;
        re = c.re;
        im = c.im;
}


void Complex::print()
{
        cout << "real = " << re << endl;
        cout << "imaginary = " << im << endl;
}

int main()
{
        Complex a = 2;
        a.print();
        Complex b = a;
        b.print();
}
Run Code Online (Sandbox Code Playgroud)

650*_*502 9

当你写作

Complex a = 2;
Run Code Online (Sandbox Code Playgroud)

编译器不会直接调用Complex构造函数使用0作为构建的默认参数,a而是考虑它是否可以"转换"2到a Complex.

要进行转换,它会找到你的Complex(re,im)版本并且可以使用它,这要归功于默认值以及你没有声明构造函数的事实explicit,但是它必须找到一种方法来传递这个值a.

这种"转移"的工具可以是复制构造函数.但是,可以构建的复杂值Complex(re,im)是临时的,并且由于C++中的一些可疑原因,不允许将临时作为非const引用传递给函数.

所以你的拷贝构造函数不能和​​临时一起使用,编译器会被卡住,因为没有办法a用2 初始化.

如果您声明您的复制构造函数而不是接受const引用,那么临时可以传递给您的复制构造函数进行初始化a,因此一切都按预期工作.

a可以使用语法直接初始化Complex a(2),在这种情况下不需要使用复制构造函数.

还要注意,当您使用语法时Complex a = ...,编译器必须检查使用复制构造函数是否合法,这可能很奇怪,但一旦检查了该合法性,就不允许调用它并使用直接初始化.换句话说,即使你需要声明你的复制构造函数接受一个const引用仍然能够编译,编译器实际上可能会跳过该部分并直接构建a而不调用复制构造函数(即使复制构造函数 - 如你的情况一样)副作用).添加了这个显然是疯狂的规则,以便能够在生成的代码中进行一些优化.

  • 为了完整性,应该注意这是直接(`()`)初始化和复制(`=`)初始化之间的区别:复制构造函数不用于直接初始化(好吧,除非参数是相同的键入作为被初始化的对象,显然,因此不会进行可用性检查.如果我们说过'Complex a(2);`而不是`Complex a = 2;`,就没有问题了. (2认同)
  • +1:最后,答案实际上解释了_why_在这种情况下需要`const`! (2认同)