3

我一直在查看我正在处理的一些代码,我们有这样的等价物:

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++ 习惯用法,例如,编写调用负责清理参数的构造函数的代码?我见过的大多数代码似乎都没有这样做......

4

3 回答 3

3

显而易见的解决方案似乎是将临时传递AutoPtr<A>给 的构造函数B

AutoPtr<B> y(new B(AutoPtr<A>(x));

B*(这也为返回的 from增加了资源控制new B())。

B的构造函数只会调用x.Detach()初始化它需要用A*. 如果任何时候发生异常,AutoPtr<A>都会释放该对象。

如果要在发生异常时保留A管理的对象x,可以将 a 传递AutoPtr<A>&给构造函数B

于 2012-10-10T00:26:06.333 回答
3

...它应该注意删除参数本身(或者应该删除?)

不,不应该。

B在构造函数完成之前不存在,如果它不存在,则不应声称拥有任何东西(在某种程度上;如果构造函数本身做了某事,那也需要是安全的)。

C++ 习惯用法是不使用原始指针来表示所有权(包括 for y)!B应该接受AutoPtr作为参数,以便调用者可以通过这种方式放弃所有权。这是std::unique_ptrand的目标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));

但这目前作为疏忽而缺失。

于 2012-10-10T00:28:50.283 回答
0

像这样的东西,可能是:

B* y = new B();
y->Attach(x.Detach());

或者

B* y = new B();
(*y) = x;
于 2012-10-10T00:29:28.833 回答