c++ - 在自己的析构函数中移动对象
问题描述
如果我有一个最初由 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 使用指针是否为空。
解决方案
A 在销毁时将自己释放回其经理是否有效?
“有效”在什么意义上?会编译吗?是的。
这有什么意义吗?不。
您正在移动一个正在被破坏的对象。该对象的所有者请求并期望该对象管理的资源不再存在。通过将这些资源还给经理,它们将继续存在。
基本上,你所拥有的是假装共享所有权。经理可以假装与您共享所有权,但实际上,它始终拥有对象,并且永远不会放弃对这些资源的真正所有权。它就像 a shared_ptr
,只是它的使用次数永远不能超过 2。
A
此外,与适当的共享指针不同,没有明显的保护措施应该比其管理器更长寿。A
该引用将简单地引用一个被破坏的对象,当实例被破坏时导致 UB 。
如果您想共享所有权,请共享它。如果你不这样做,那就不要。但是这种半状态会使您的代码变得脆弱。
推荐阅读
- c - 使用其他选项改进 for() 循环
- python - 如何合并多个 mp3 文件并保持静音?
- javascript - 单击确认时JavaScript确认框不起作用
- spring-boot - spring boot中使用redis扫描命令时如何设置起始点
- c++ - 是否有任何 API 像 `llvm::InitializeX86Targets()` 仅适用于 LLVM 中的 X86 目标机器?
- java - Java ZGC 垃圾收集器占用大量内存
- python - 循环遍历熊猫数据框并提取选择列数据
- c# - MS Graph - LINQ 查询返回不正确的结果
- javascript - 为什么没有呈现函数结果
- java - IntelliJ JavaFX Maven 运行:无法识别的选项:--module-path