c++ 为什么在通过继承禁用复制语义的情况下,将位置放回vector不起作用

efzxgjgh  于 2023-08-09  发布在  其他
关注(0)|答案(1)|浏览(95)

我试图找出为什么在下面的例子中,当我禁用复制语义但保留移动语义时,将其放置到 std::vector 在一种情况下有效,但在另一种情况下(当使用继承时)无效:

#include <iostream>
#include <vector>

class NonCopyable
{
  public:
    NonCopyable(const NonCopyable &) = delete;
    NonCopyable(NonCopyable &&) noexcept = default;
    NonCopyable &operator=(const NonCopyable &) = delete;
    NonCopyable &operator=(NonCopyable &&) noexcept = default;

    NonCopyable() = default;
    virtual ~NonCopyable() = default;
};

// NOTE: here things works as long as I dont override the destructor. If I do, it stops.
class MyClass : public NonCopyable
{
  public:
    MyClass() = default;
    
    // NOTE: when commented out, all compiles fine, otherwise not
    ~MyClass() override {}
};

// NOTE: when all is put into a single class, everything compiles ok
class MyClass2
{
  public:
    MyClass2() = default;
    ~MyClass2() noexcept
    {
    }

    MyClass2(const MyClass2 &) = delete;
    MyClass2 &operator=(const MyClass2 &) = delete;
    MyClass2(MyClass2 &&) noexcept = default;
    MyClass2 &operator=(MyClass2 &&) noexcept = default;
};

int main()
{
    std::vector<MyClass> mc;
    MyClass a;
    mc.emplace_back(std::move(a));

    std::vector<MyClass2> mc2;
    MyClass2 a2;
    mc2.emplace_back(std::move(a2));
}

字符串
在线编译器中的示例:https://onlinegdb.com/UTWju9WkU
我错过了什么?谢谢你,谢谢

pcww981p

pcww981p1#

5的规则指出,如果你触摸5个特殊成员函数(复制ctor,复制赋值,移动ctor,移动赋值,dtor)中的任何一个,你应该触摸它们。不这样做是一个糟糕的计划。(5的规则也被称为3的规则,从后退到移动操作存在)。
在这种情况下,当您实现~MyClass()时,编译器不再合成您的移动构造函数。emplace_back需要使用move构造函数,因为如果调整了向量的大小,就会用到它。
标准有确切的规则,但你不需要记住它们。你只需要记住5的规则。
(The这里要知道的另一条规则是0规则--除非您正在编写资源管理类,否则不要碰它们。如果你正在编写一个资源管理类,它应该只做资源管理;使用组合将资源存储在业务逻辑类中。然后,您的业务逻辑类遵循0规则,并从其成员获得其移动/复制/销毁语义。)

相关问题