C 复制构造函数在返回时称为

C++ copy constructor called at return

本文关键字:返回 复制 构造函数      更新时间:2023-10-16
error: use of deleted function 'A::A(const A&)'
 return tmp;
        ^~~

为什么只有在A中有虚拟破坏者时才调用复制构造函数?如何避免这种情况?

struct B {};
struct A{
    std::unique_ptr<B> x;
    virtual ~A() = default;
};
A f() {
    A tmp;
    return tmp;
}

virtual ~A() = default;是用户声明为destructor。因此,A不再具有移动构造函数。这意味着return tmp;无法移动tmp,并且由于tmp无法复制,因此您会收到编译器错误。

有两种方法可以解决此问题。您可以添加一个移动构造函数,例如

struct A{
    std::unique_ptr<B> x;
    A() = default; // you have to add this since the move constructor was added
    A(A&&) = default; // defaulted move
    virtual ~A() = default;
};

或者您可以创建一个具有虚拟破坏者并从中继承的基类

struct C {
    virtual ~C() = default;
};
struct A : C {
    std::unique_ptr<B> x;
};

这起作用是因为A不再具有用户声明为destructor(是的,C可以,但我们只关心A),因此它仍然会在A中生成移动构造函数。重要的部分是C没有删除的移动构造函数,它只是没有一个时期,因此尝试移动它会导致副本。这意味着 C的复制构造函数在A的隐含生成的移动构造器中被调用,因为C(std::move(A_obj_to_move_from))只要没有删除的移动构造函数即可复制。