在 class 主体中声明析构函数且 unique_ptr 作为同一 class 的成员时出现编译器错误

Compiler error when destructor declared in class body with unique_ptr as member of the same class

下面是代码的极简问题:

struct B { 
  B () = default;
  //~B () {};  // error: use of deleted function ‘B& B::operator=(const B&)’
  std::unique_ptr<int> m_pB = nullptr;
};

int main ()
{
  std::vector<B> vB; 
  vB.erase(vB.begin());
}

以上代码可以正常编译,除非取消注释析构函数。根据我的要求,我需要明确定义 ~B() 的正文。

如何定义与 unique_ptr 共存于同一个 class 的析构函数体?

注意:尝试定义 = default 版本的复制和移动构造函数无济于事。在我的真实代码中,unique_ptr<int>unique_ptr<forward_declared_class>。无法在 SO 中找到此问题,但我确信它一定存在。随意标记为欺骗。

您可以声明并实现编译器要求的移动赋值运算符。当然,它会抱怨复制赋值,但是对于您的结构来说,合理的复制似乎是不可能的。

错误消息可能有点误导,因为 std::vector::erase 实现在代码中包含类似 _data[i-1] = _data[i] 的内容,该代码将矢量元素插入已删除项目的位置。所以编译器需要任何赋值运算符,我们为它提供一个移动的。

例如,这工作正常(gcc 4.8.3):

struct B { 
  B () = default;
  B& operator=(B&& op) {
    m_pB = std::move(op.m_pB);
    return *this;
  }
  ~B () {};  // no more errors.
  std::unique_ptr<int> m_pB = nullptr;
};

int main ()
{
  std::vector<B> vB; 
  vB.erase(vB.begin());
}

似乎您的代码需要 B 可复制构造并可复制分配给 std::vector(至少对于我测试过的 visual c++)。

复制构造函数和复制赋值运算符只能是 = delete 因为 std::unique_ptr(声明 = default 的实现也应该导致函数被删除),并且通过实现析构函数,您禁用移动构造函数和移动赋值运算符的默认实现。

因此您需要显式声明移动赋值运算符。尝试:

#include <memory>
#include <vector>

struct B { 
  B () = default;
  ~B () {}
  B& operator=(B&&) = default;
  std::unique_ptr<int> m_pB = nullptr;
};

int main ()
{
  std::vector<B> vB; 
  vB.erase(vB.begin());
}

矢量代码是一条红鲱鱼。

当一个classU有一个unique_ptr类型的成员,并且T是前向声明的,析构函数的定义必须在cpp文件中,当U不再是一个不完整的类型。

你应该有 ~U();在 header 和 cpp 文件中有 U::~U(){} 或 U::~U() = default;