Search code examples
c++c++17move

Move object within its own destructor


If I have a move-only class which is initially owned by AManager, can be transferred to another owner via obtain, returned back to AManager via release.

class AManager;

class A {
public:
    A(const A& other) = delete;
    const A& operator=(const A&) = delete;

    A(A&& other);
    A& operator=(A&& other);

private:
    AManager& _manager;
    bool _isValid;
};

class AManager {
public:
    A obtain() {
        return std::move(_instance);
    }
    void release(A a) {
        _instance = std::move(a);
    }

private:
    A _instance;
};

Is it valid for A to move itself within its own destructor? i.e., is it valid for A to release itself back to its manager when it is destroyed?

A::~A() {
    if (_isValid) {
        _manager.release(std::move(*this));
    }
}

Assuming the A class has some way to know if its in a valid state. For example, I added a valid flag. I believe unique_ptr uses the pointer being null or not.


Solution

  • is it valid for A to release itself back to its manager when it is destroyed?

    "Valid" in what sense? Will it compile? Yes.

    Does it make any kind of sense? No.

    You are moving an object that is being destroyed. The owner of that object requested and expects the resources managed by this object to no longer exist. By giving those resources back to the manager, they will continue to exist.

    Basically, what you have is pretend-shared-ownership. The manager can pretend to share ownership with you, but in reality, it always owned the object and true ownership of those resources can never be relinquished. It's like a shared_ptr, except that its use count can never exceed 2.

    Also, there are no apparent safeguards in place should A outlive its manager, unlike with a proper shared pointer. The reference will simply reference a destroyed object, leading to UB when the A instance is destroyed.

    If you want to share ownership, then share it. If you don't, then don't. But this half-state makes your code brittle.