Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用委托构造函数避免泄漏_C++_C++11_Memory Leaks - Fatal编程技术网

C++ 使用委托构造函数避免泄漏

C++ 使用委托构造函数避免泄漏,c++,c++11,memory-leaks,C++,C++11,Memory Leaks,在一次谈话中,以下代码被证明是不安全的,因为如果构造函数抛出,将不会调用析构函数并泄漏资源: class TwoResources { TwoResources(int x, int y) : m_a(nullptr), m_b(nullptr) { m_a = new A(x); m_b = new B(y); } ~TwoResources() { delete m_b; delete m_a; } A

在一次谈话中,以下代码被证明是不安全的,因为如果构造函数抛出,将不会调用析构函数并泄漏资源:

class TwoResources {
    TwoResources(int x, int y)
        : m_a(nullptr), m_b(nullptr) {
        m_a = new A(x); m_b = new B(y);
    }
    ~TwoResources() {
        delete m_b; delete m_a;
    }
    A * m_a; B * m_b;
};
建议解决方案是使用委托构造函数,如下所示:

class TwoResources {
    TwoResources() : m_a(nullptr), m_b(nullptr) { }
    TwoResources(int x, int y) : TwoResources() {
        m_a = new A(x); m_b = new B(y);
    }
    ~TwoResources() {
        delete m_b; delete m_a;
    }
    A * m_a; B * m_b;
};
这是安全的,因为:

C++11 15.2[except.ctor]/2:“如果 对象已完成执行,并为此创建了一个委托构造函数 对象存在时出现异常,对象的析构函数将 调用。”

但在同一张幻灯片中,它说:

仅仅因为你可以利用这条规则并不意味着你应该这样做


如果这段代码被保证是安全的,那么它有什么潜在的问题吗?

仅仅因为某些东西是安全的并不意味着这样做是一个好主意

例如,使用委托构造函数调用对于异常安全至关重要,但对于不熟悉该语言复杂性的代码普通读者来说,这还远远不够清楚。一个月后,其他人查看您的代码时可能会想“如果您再次在构造函数体中设置它,为什么要将其设置为null?”并将其删除。哎哟


此外,当您手动管理生命周期时,您需要编写自己的复制/移动构造函数/赋值运算符。错过一个,结果就大破坏。如果您使用
唯一\u ptr
来管理生存期,那么编译器生成的移动构造函数/赋值运算符和析构函数将做正确的事情,并且如果您试图复制而自己没有实现复制构造函数,它会抱怨。

这当然不清楚。有人可以通过只在一个构造函数中添加新变量来修改代码,而不了解第二个构造函数的用途。 你应该考虑使用

class资源
{
两个资源(intx,inty):m_a(新的a(x)),m_b(新的b(y))
{
}
std::unique_ptr比手动使用new和delete运算符更安全:

class TwoResources 
{
    TwoResources(int x, int y):m_a( std::make_unique<A>( x ) ), m_b( std::make_unique<B>(B( y ) )
    {
    }
    std::unique_ptr<A> m_a;
    std::unique_ptr<B> m_b;
};
class资源
{
两个资源(intx,inty):m_a(std::make_unique(x)),m_b(std::make_unique(b(y))
{
}
std::唯一的ptr m_a;
std::唯一的ptr m_b;
};

在c++11代码中手动使用
new/delete
可能是个坏主意。您应该使用智能指针来避免此类问题。这是STL在GoingNative 2013上的演讲,对吗?我认为类名
twooresources
暗示了一个更可行的解决方案;每个类(或对象)一个资源。如果两个资源的管理不同,请将每个资源包装在各自的RAII类中,并使其成为更高级别类的成员。
class TwoResources 
{
    TwoResources(int x, int y):m_a( std::make_unique<A>( x ) ), m_b( std::make_unique<B>(B( y ) )
    {
    }
    std::unique_ptr<A> m_a;
    std::unique_ptr<B> m_b;
};