如何安全地将new创建的对象传递给构造函数

时间:2017-11-22 07:44:44

标签: c++ c++11 pointers memory-management class-design

我有几个看起来像这样的课程:

struct equation {};

struct number: equation {
    number(int n): value(n) {}

  private:
    int value;
};

struct operation: equation {
    operation(const equation* left, const equation* right)
        : left(left), right(right) {}

  private:
    std::unique_ptr<equation> left, right;
};

它们的设计方式是operation取得传递给构造函数的指针的所有权。

我的问题是如何修改此类以便能够以下一种方式安全地使用它:

operation op(new number(123), new number(456));

在我看来,如果第一个对象被创建而第二个对象没有(比如从number构造函数抛出异常)那么它就是内存泄漏 - 没有人会删除指向第一个号码。

这种情况该怎么办?我不想按顺序分配对象,如果出现故障则删除它们 - 它太冗长了。

1 个答案:

答案 0 :(得分:10)

  

我不想按顺序分配对象,如果出现故障则删除它们 - 它太冗长了。

是。你只需要更彻底地应用智能指针习语;更确切地说,将参数类型更改为std::unique_ptr,并使用std::make_unique (since C++14)(而不是显式使用new)来避免此问题。 e.g。

struct operation: equation {
    operation(std::unique_ptr<equation> left, std::unique_ptr<equation> right)
        : left(std::move(left)), right(std::move(right)) {}

  private:
    std::unique_ptr<equation> left, right;
};

然后

operation op(std::make_unique<number>(123), std::make_unique<number>(456));

请注意,std::make_unique的使用非常重要,std::make_unique内创建的原始指针可以保证由返回的std::unique_ptr管理;即使是第二个std::make_unique也失败了 由std::unique_ptr创建的std::make_unique将确保它拥有的指针被销毁。对于首先调用第二个std::make_unique的情况也是如此。

在C ++ 14之前,您可以制作自己的std::make_unique版本;基本的一个很容易写。 Here是一种可能的实施方式。

// note: this implementation does not disable this overload for array types
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}