【问题标题】:Move object within its own destructor在自己的析构函数中移动对象
【发布时间】:2021-09-08 19:39:08
【问题描述】:

如果我有一个最初由 AManager 拥有的只移动类,可以通过 obtain 转移给另一个所有者,通过 release 返回给 AManager。

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 使用的指针是否为空。

【问题讨论】:

  • 我不明白为什么会神奇地不允许它。这只是一个完全正常的函数调用,您通过右值引用将对象传递给它。
  • 它是否打算让A 具有附加功能?所以A 将负责其主要目的 负责确保资源返回到AManager?一堂课有两个任务?
  • 嗯...移动*this 的想法可能需要将此问题与近乎重复的问题分开,但您仍可能需要查看Usage of "this" in destructorValidity of "this" in destructor
  • 为什么要编写充满未定义行为且难以理解的代码。从它的析构函数到move *this 完全没有意义。
  • @Phil1970 将*this 移动到_instance 不会导致_instance 与已被销毁的对象完全相同。相反,它会导致_instance 成为*this 的副本,并且可以选择非常有效地完成此副本。然而,你在一个问题的边缘跳舞:当经理被摧毁时会发生什么?经理被销毁后,其成员也被销毁,包括_instance。当_instance 被销毁时,它可能会尝试将自己释放给不再有效的管理器。

标签: c++ c++17 move


【解决方案1】:

当A被销毁时,将自己释放回其管理器是否有效?

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

这有什么意义吗?没有。

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

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

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

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

【讨论】:

  • C++ 运行时不会破坏operator deleted 内存,而是将其返回到空闲存储区以供以后重用(无论如何您将如何破坏内存?)其他资源不需要不同。将它们返回给各自的资源管理器没有任何问题。
  • @n.1.8e9-where's-my-sharem.: 除非资源管理器在您拥有资源时被销毁。这就是共享所有权的意思:当两段或多段代码负责破坏一个事物时。如果它由资源管理器唯一拥有,那么它应该归用户所有;他们应该只是借用它的引用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-26
  • 2021-01-20
  • 2012-12-26
  • 2012-11-27
  • 1970-01-01
  • 2011-05-04
  • 2016-02-10
相关资源
最近更新 更多