首页 > 解决方案 > 在自己的析构函数中移动对象

问题描述

如果我有一个最初由 AManager 拥有的只移动类,可以通过 转移给另一个所有者obtain,通过返回给 AManager 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;
};

A 在自己的析构函数中移动自己是否有效?即,当 A 被销毁时,将自己释放回其管理器是否有效?

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

假设 A 类有某种方法可以知道它是否处于有效状态。例如,我添加了一个有效标志。我相信 unique_ptr 使用指针是否为空。

标签: c++c++17move

解决方案


A 在销毁时将自己释放回其经理是否有效?

“有效”在什么意义上?会编译吗?是的。

这有什么意义吗?不。

您正在移动一个正在被破坏的对象。该对象的所有者请求并期望该对象管理的资源不再存在。通过将这些资源还给经理,它们将继续存在。

基本上,你所拥有的是假装共享所有权。经理可以假装与您共享所有权,但实际上,它始终拥有对象,并且永远不会放弃对这些资源的真正所有权。它就像 a shared_ptr,只是它的使用次数永远不能超过 2。

A此外,与适当的共享指针不同,没有明显的保护措施应该比其管理器更长寿。A该引用将简单地引用一个被破坏的对象,当实例被破坏时导致 UB 。

如果您想共享所有权,请共享它。如果你不这样做,那就不要。但是这种半状态会使您的代码变得脆弱。


推荐阅读