我一直在研究一些我正在研究的代码,我们有相同的代码:
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 ++习惯用法,例如,调用构造函数的代码负责清理参数?我见过的大多数代码似乎都不这么做......
答案 0 :(得分:3)
显而易见的解决方案似乎是将临时AutoPtr<A>
传递给B
的构造函数:
AutoPtr<B> y(new B(AutoPtr<A>(x));
(这也为从B*
返回的new B()
添加了资源控制。
B
的构造函数只需调用x.Detach()
来初始化使用A*
进行初始化所需的任何内容。如果在任何时候发生异常,AutoPtr<A>
将释放该对象。
如果您希望在发生异常时保留A
管理的x
对象,则可以将AutoPtr<A>&
传递给B
的构造函数。
答案 1 :(得分:3)
...它应该注意删除参数本身(或者它应该?)
不,它不应该。
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));
但目前缺少这种疏忽。
答案 2 :(得分:0)
这样的事情可能是:
B* y = new B();
y->Attach(x.Detach());
或
B* y = new B();
(*y) = x;