Does a default virtual destructor prevent compiler-generated move operations?

℡╲_俬逩灬. 提交于 2019-12-03 04:21:35

Yes, declaring any destructor will prevent the implicit-declaration of the move constructor.

N3337 [class.copy]/9: If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if

  • X does not have a user-declared copy constructor,
  • X does not have a user-declared copy assignment operator,
  • X does not have a user-declared move assignment operator,
  • X does not have a user-declared destructor, and
  • the move constructor would not be implicitly defined as deleted.

Declaring the destructor and defining it as default counts as user-declared.

You'll need to declare the move constructor and define it as default yourself:

WidgetBase(WidgetBase&&) = default;

Note that this will in turn define the copy constructor as delete, so you'll need to default that one too:

WidgetBase(const WidgetBase&) = default;

The rules for copy and move assignment operators are pretty similar as well, so you'll have to default them if you want them.

Not a solution, but one of possible workarounds. You can inherit all of your classes from a class that has only default virtual destructor.

I checked using GCC 9 and Apple's Clang++ with -std=c++17: both of them generate move constructors for classes that inherit the class below.

class Object {
public:
    virtual ~Object() = default;
};

The class below will indeed have a move constructor.

class Child : public Object {
public:
    Child(std::string data) : data(data) {
    }

private:
    std::string data;

};

Another possible but risky workaround would be to not declare virtual destructors at all. It would introduce the following risks:

  • All objects must always be destructed by someone who knows their exact type. Which is not really that big of a problem in a nicely designed C++ code.
  • When object of such class is stored in a container like std::vector or std::list it must always be wrapped using std::shared_ptr. std::unique_ptr would cause leaks! That's related to their differences related to storing deleter.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!