与构造函数参数相关的异常安全的习语
Idiom for exception safety relating to constructor parameters
我一直在看我正在处理的一些代码,我们有这样的等价物:
AutoPtr<A> x;
...
/// x gets initialized
...
B* y = new B(x.Detach());
其中 AutoPtr 是我们auto_ptr的版本,Detach() 返回拥有的指针并重置自身。此外,B() 拥有 x 的所有权。
现在,我意识到如果 new 抛出 std::bad_alloc,这将泄漏 x,所以我将代码更改为:
AutoPtr<A> x;
...
/// x gets initialized
...
B* y = new B(x.Get());
x.Detach();
但后来我意识到,如果 B() "拥有"指针,并且在其构造过程中发生异常,它应该负责删除参数本身(或者应该删除?),所以 x 将被删除两次,一次由 B(),一次由 x 的析构函数删除。
现在,是否有一个C++习语可以解决此问题,例如,制作调用负责清理参数的构造函数的代码?我见过的大多数代码似乎都没有这样做......
显而易见的解决方案似乎是将临时AutoPtr<A>
传递给 B
的构造函数:
AutoPtr<B> y(new B(AutoPtr<A>(x));
(这也为从new B()
返回的B*
添加了资源控制)。
B
的构造函数只会调用 x.Detach()
来初始化它需要用A*
初始化的任何内容。如果在任何时候发生异常,AutoPtr<A>
将释放对象。
如果要保留由 x
管理的A
对象以防发生异常,则可以改为将AutoPtr<A>&
传递给 B
的构造函数。
。它应该负责删除参数本身(或者应该删除?
不,不应该。
B
在构造函数完成之前不存在,如果它不存在,它不应该声明任何内容的所有权(在某种程度上;如果构造函数本身做了某事,那也需要是安全的)。
C++习语是不要使用原始指针进行所有权(包括y
)! B
应该接受AutoPtr
作为参数,以便调用方可以通过这种方式放弃所有权。这是std::unique_ptr
和std::move
的目标:
std::unique_ptr<A> x;
std::unique_ptr<B> y(new B(std::move(x)));
另请注意,真的new
也不应该像这样使用;而是使用make_*
实用程序:
auto y = std::make_unique<B>(std::move(x));
但目前缺少作为监督。
像这样的东西,可能是:
B* y = new B();
y->Attach(x.Detach());
或
B* y = new B();
(*y) = x;
- 概念可以与 CRTP 习语一起使用吗?
- 复制和交换习语和迭代器
- 为什么当我做复制和交换习语时不调用我的复制构造函数?
- 漂亮的计数器习语的错误或格式错误的静态订单惨败?
- C++17 pimpl 习语上下文中的自定义迭代器
- 在 MyVector 中实现写入时复制习语
- 视觉 "extern __forceinline "是什么 c++ 习语?
- C 习语使用C库时,该C库期望功能指针
- 为什么 std::swap 不使用 swap 习语?
- 如何使用擦除删除习语从结构向量中删除值
- C++中的Singleton习语
- 在 C++11 中实现复制和交换习语的更好方法
- N 个并发读取器和 1 个生产者的习语或模式
- pImpl习语-将私有类实现放在cpp中有什么缺点
- 不能使用 pimpl 习语将用户定义的向量插入到封装的向量中
- Python -> C++ 习语:将 lambda 表达式存储在映射/容器中
- 安全方便的通用散列(用于 STL 无序集和映射)习语?
- 指向可配置实现的Pimpl习语
- 与构造函数参数相关的异常安全的习语
- 用C++处理身体习语