在构造函数初始化器中传递new的对象是明智还是愚蠢?
例如:
class Mallard
{
public:
Mallard()
: s(new SomeLargeObject(5)) {}
private:
SomeLargeObject * s;
};
在构造函数初始化器中传递new的对象是明智还是愚蠢?
例如:
class Mallard
{
public:
Mallard()
: s(new SomeLargeObject(5)) {}
private:
SomeLargeObject * s;
};
如果您忘记发布析构函数并且该析构函数进行对称删除,则代码示例中没有机械损坏。
虽然传统做法(更安全,更少的样板代码)是希望有类似以下的内容:
#include <memory>
class Mallard {
std::unique_ptr<SomeLargeObject> that_;
public:
Mullard(): that_(new SomeLargeObject)
{}
// this way you don't need to code the destructor
};
std::unique_ptr
的语法不会受到此问题的影响( 这就是它安全的原因)。如果我可以发表个人意见:
第一点:一般来说,将s作为SomeLargeObject类型的成员变量会更好,并且不必担心动态内存分配;
第二点:有时在构造函数中分配东西很有用,只要你小心,就没有问题。特别是对于像这样的桥接模式非常有用:
// Abstract base of all beaks
class Beak
{
public:
};
// Abstract base of all birds
class Bird
{
protected:
const Beak *beak;
~Bird()
{
delete beak;
}
};
class MallardBeak : public Beak
{
};
class Mallard : public Bird
{
public:
Mallard() : beak(new MallardBeak) { }
};
class PigeonBeak : public Beak
{
};
class Pigeon : public Bird
{
public:
Pigeon() : beak(new PigeonBeak) { }
};
new
的话,加入第二个动态分配就有可能会泄漏。即使只有一个动态分配成员,使用unique_ptr
或shared_ptr
来管理仍然更好。 - Praetoriandelete
以防止明显的内存泄漏。但是,如果你初始化第二个成员,比如说Mallard():s(new Foo()), s2(new Bar()) {}
并且第二个分配失败了,析构函数将不会被调用,从而导致s
泄漏。 - Praetoriandelete
它。我试图说明的重点是管理原始指针以及其他数据成员容易出错,请使用智能指针。请注意,所有这些都适用于您管理的任何类型的资源(文件、套接字等),而不仅仅是内存。 - PraetorianMallard():s(new Foo()), s2(new Bar()) {}
这样的代码,且s(new Foo())
成功执行,然后s2(new Bar())
抛出异常,那么~Mallard()
就不会被调用,导致s
被泄露。除非声明s
为智能指针(如auto_ptr<Foo> s
或unique_ptr<Foo> s
),在这种情况下,智能指针的析构函数将会被调用(当构造函数抛出异常时,已经构造的成员就会被销毁),内存将按预期释放。 - Remy Lebeau