智能指针是否排除了两阶段构造的需要?
Do smart pointers preclude the need for two-phase construction?
两阶段结构采用以下形式:
struct something {
something ()
: p1(NULL)
, p2(NULL)
{ }
~something () {
if (p1) delete p1;
if (p2) delete p2;
}
void initialize () {
p1 = new int(2);
p2 = new int(5); // May throw if allocation fails!
}
int* p1;
int* p2;
};
简单构造函数(不监视分配失败)会泄漏内存:部分构造对象的析构函数永远不会被调用。
我的问题是:下面的代码安全吗?根据推论,智能指针是否可以避免两阶段构造?
struct something {
something ()
: p1(new int(2))
, p2(new int(5))
{ }
std::unique_ptr<int> p1;
std::unique_ptr<int> p2;
};
是的,您的新代码很好。但是请注意,在更复杂的情况下可能会有一个微妙的
#include <memory>
struct foo {
foo(std::shared_ptr<int> a, std::shared_ptr<int> b) { }
};
struct bar {
foo f;
bar() : f(std::shared_ptr<int>(new int), std::shared_ptr<int>(new int)) { }
};
int main() {
bar b;
}
但是不是安全的,因为bar
的初始化列表中foo
的构造函数的参数的求值顺序是未指定的。符合标准的编译器可能会选择进行深度或广度的第一阶求值(或者其他任何东西,只要它们最终都得到了正确的求值)。这意味着如果第一个new int
成功,但是第二个在shared_ptr
对象构造之前抛出,那么执行的第一个分配仍然可能泄漏。
如果您发现自己想要这样做,除了回到两阶段构造之外,还有两种可能的解决方案:第一种可能是重构,第二种可能是首先将shared_ptr
单独构造为bar的成员,然后再构造f
。哪一种最合适,我认为需要根据具体情况做出判断。
我的问题是:下面的代码安全吗,
可以,可以。
struct something {
something ()
: p(new int(5))
{ }
std::unique_ptr<int> p;
};
注意幼稚代码
struct something {
something ()
: p(new int(5))
{ }
int* p;
};
也是异常安全的,因为只有一个分配会失败。我想你说的是
struct something {
something ()
: p(new int(5)), q(new int)
{ }
int *p, *q;
};
不会。在这种情况下,智能指针也可以工作。
如果您只是处理异常,则根本不需要两阶段构造。这是RIAA的方式。
struct something {
something ()
: p1(NULL)
, p2(NULL)
{
p1 = new int(2);
try {
p2 = new int(5); // May throw if allocation fails!
} catch (std::bad_alloc&) {
delete p1; //cleanup
throw; //rethrow
}
}
~something () {
delete p1;
delete p2;
}
int* p1;
int* p2;
};
相关文章:
- 如果基类包含双指针成员,则派生类的构造函数
- 声明没有默认构造函数的字段
- 复制构造函数C++无法正确复制指针
- 从堆栈分配的原始指针构造智能指针
- 为什么下面的代码段返回指针指向的值而不是指针的地址?
- 运行几次后合并段错误C++(指针算术)
- 作为C++结构中成员数据字段的指针
- 是否会自动删除已添加到重复字段的指针
- 对于构造指针类型的 std::set 是有效的
- 理解这段涉及指针、数组和新运算符的代码
- 如果超构造函数不使用派生类字段,是否可以将该指针传递给该指针?
- 通过函数模板传递时,无法从0构造指针
- 段错误指针
- 存储指向特征向量"段"的指针而不复制?
- 是否声明抽象类型的字段?首选指针或引用
- 指向成员字段的指针适配器
- Unique_ptr和默认的可构造指针
- 代码段中指针的模糊行为
- c++复制构造函数:带有指针列表的字段
- 逐字段构造函数生成的规则是什么?