【问题标题】:Vector of objects with a unique_ptr member and custom destructor具有 unique_ptr 成员和自定义析构函数的对象向量
【发布时间】:2020-09-06 22:22:41
【问题描述】:

假设以下代码将A 类型的对象移动到av(向量):

#include <memory>
#include <vector>

struct A
{
    ~A() {};

    std::unique_ptr<int> an_int;
};


int main(int argc, char* argv[])
{
    std::vector<A> av;
    av.push_back(A());

    return 0;
}

这将无法按原样编译。但是,如果我不实现析构函数~A() {},它就可以正常工作。编译器提示一些缺失(已删除)copy constructor,但我看不到这适用于这里(因为我只做移动操作)

unique_ptr和导致代码编译失败的自定义析构函数是什么关系?有一个简单的解决方法吗?

谢谢。

【问题讨论】:

  • push_back 复制,也许你在想emplace_back。缺少编译器生成的复制构造函数,因为您无法复制 unique_ptr。
  • @MarkRansom 对于右值引用,push_back 存在重载,它移动元素而不是复制。
  • 除了下面的答案,请参阅幻灯片 #30 here
  • this page 的最底部,Howard Hinnant 有一个有用的特殊成员函数表,当用户声明其他特殊成员函数时,这些函数会被隐式默认、删除或禁止。 (这与 HolyBlackCat 链接的幻灯片 #30 相同。)

标签: c++ c++17


【解决方案1】:

定义自定义析构函数会禁用默认移动构造函数和移动赋值运算符的生成。因此使用了push_back(const A&amp;),但A 也没有复制构造函数,因为它有unique_ptr 成员。

解决方案是手动将它们定义为default。但是定义移动构造函数会禁用默认构造函数:

struct A
{
    ~A() {};
    A()=default;
    A(A&&)=default;
    A& operator=(A&&)=default;
    std::unique_ptr<int> an_int;
   
};
static_assert(std::is_nothrow_move_constructible_v<A>);
static_assert(std::is_nothrow_move_assignable_v<A>);

【讨论】:

    【解决方案2】:

    当您定义析构函数时,编译器不会生成移动/复制构造函数,因为您只是暗示对象的构造/析构不是微不足道的。见this answer

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-27
      • 2020-07-29
      • 2017-11-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多