为什么在执行显式转换时转换构造函数需要声明复制构造函数?

问题描述

据我所知,我认为 Foo a = 1 等价于 Foo a = (Foo)1

声明复制构造函数后,是的,它们都导致调用 Converting constructor

class Foo
{
public:
    // Converting constructor
    Foo(int n) : value_(n) { std::cout << "Converting constructor." << std::endl; }

    // copy constructor
    Foo(const Foo&) { std::couut << "copy constructor." << std::endl; }

private:
    int value_;
};

int main()
{
    Foo a = 1;         // OK - prints only "Converting constructor."
    Foo b = (Foo)1;    // OK - prints only "Converting constructor."
}

相比之下,如果没有复制构造函数,即使它从不调用复制构造函数,它也不会编译。

class Foo
{
public:
    // Converting constructor
    Foo(int n) : value_(n) { std::cout << "Converting constructor." << std::endl; }
    
    // copy constructor deleted
    Foo(const Foo&) = delete;

private:
    int value_;
};

int main()
{
    Foo a = 1;         // OK - prints only "Converting constructor."
    Foo b = (Foo)1;    // Error C2280: 'Foo::Foo(const Foo &)': attempting to reference a deleted function
}

有什么不同? 谢谢。

解决方法

Foo a = 1; 调用 Foo(int n)(Foo)1 也调用 Foo(int n)Foo b = (Foo)1; 调用复制构造函数 Foo(const Foo&)。在 C++17 之前,可以省略最后一次调用,但复制构造函数必须可用。由于 C++17 复制省略是强制性的,并且复制构造函数不是必需的:https://en.cppreference.com/w/cpp/language/copy_elision

可能您使用的是 C++17 之前的 C++ 标准,并且需要但未调用复制构造函数。

“根据我的了解,我认为 Foo a = 1 等同于 Foo a = (Foo)1。” 这并不等同。第一个是一个构造函数调用,第二个是两个构造函数调用,但可以/必须省略一个调用。