返回时调用C ++复制构造函数

时间:2019-03-21 20:23:25

标签: c++

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;
}

1 个答案:

答案 0 :(得分:30)

virtual ~A() = default;是用户声明的析构函数。因此,A不再具有move构造函数。这意味着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不再有用户声明的析构函数(是的,C确实有,但我们只关心A),因此它仍会在{{1 }}。重要的部分是A没有删除的move构造函数,它没有一个句点,因此尝试移动它会导致复制。那意味着 C的副本构造函数在C的隐式生成的move构造函数中被调用,因为A只要没有删除的move构造函数就会进行复制。