0

I need a noncopyable class which has a declared destructor, and naive approach doesn't work: see https://ideone.com/mU8aoc. What's the problem with the destructor, why moving doesn't work the same way as without it? And of course, how to fix it?

For reference, the complete code (same as by the ideone link above):

class noncopyable {
public:
    noncopyable(noncopyable &&) noexcept;

    noncopyable &operator=(noncopyable &&) noexcept;

protected:
    noncopyable() = default;

    ~noncopyable() = default;

    noncopyable(const noncopyable &) = delete;

    noncopyable &operator=(const noncopyable &) = delete;
};

class C: noncopyable {
public:
    // compiles if this line is uncommented
    // C(C&& c);

    C() {}

    // also compiles if this is commented
    ~C() {}
};

C a() {
    return {};
}

C b() {
    return a();
}

int main() {
    return 0;
}
aplavin
  • 2,199
  • 5
  • 32
  • 53
  • Define "custom destructor". All destructors are "custom", for each class. – Sam Varshavchik Apr 30 '16 at 02:35
  • By "custom" I meant a destructor explicitly declared in the `C` class (see the code) - without it the example compiles. – aplavin Apr 30 '16 at 02:38
  • A superclass cannot force a subclass to have an explicitly declared destructor. A superclass can force a subclass to implement a pure virtual method. But destructors are not methods. Each class must have a destructor, if it doesn't, it gets a default destructor. There is no such thing as a "custom destructor". There's only one way a class instance gets destroyed. What's commonly called a "destructor" is some arbirary chunk of code that gets run before a class instance is really destroyed. And how a class instance is destroyed is explicitly defined by the C++ standard. – Sam Varshavchik Apr 30 '16 at 02:45

1 Answers1

1

For your code to work, class C must be moveable. When it has no declared destructor, it gets a compiler-generated implicit move constructor (and move assignment operator). But when it has a declared ("custom" in your parlance) destructor, the move constructor (and move assignment operator) are no longer provided implicitly. This is for your safety: it is assumed that if you need an explicit destructor you will need explicit move functions as well.

Reference: http://en.cppreference.com/w/cpp/language/move_constructor

John Zwinck
  • 239,568
  • 38
  • 324
  • 436