我应该在类构造函数内部还是外部初始化shared_ptr?

dys*_*oco 3 c++ smart-pointers c++11

给出以下示例代码:

#include <memory>

class Foo {
public:
    Foo(std::shared_ptr<int> p);
private:
    std::shared_ptr<int> ptr;
};

Foo::Foo(std::shared_ptr<int> p) : ptr(std::move(p)) {
}

class Bar {
public:
    Bar(int &p);
private:
    std::shared_ptr<int> ptr;
};

Bar::Bar(int &p) : ptr(std::make_shared<int>(p)) {
}

int main() {
    Foo foo(std::make_shared<int>(int(256)));
    Bar bar(*new int(512));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Foo和Bar都能正常工作.但是,在调用构造函数时创建shared_ptr然后使用std :: move传递所有权并仅传递对象的引用并将shared_ptr的创建委托给类构造函数之间是否存在任何差异?

我假设第二种方式更好,因为我不必移动指针.但是,我大多数时候都看到了我正在阅读的代码中使用的第一种方式.

我应该使用哪一个?为什么?

Ric*_*ges 6

Foo是对的.

酒吧是令人厌恶的.它涉及内存泄漏,不安全的异常行为和不必要的副本.

编辑:内存泄漏的解释.

解构这条线:

Bar bar(*new int(512));
Run Code Online (Sandbox Code Playgroud)

导致这些操作:

  1. 调用new int(512),这会调用operator new,返回指向堆上int的指针(内存分配).
  2. 取消引用指针以便为Bar的构造函数提供const引用
  3. 然后Bar使用make_shared返回的shared_ptr构造它(这部分是有效的).这个shared_ptr的int初始化为引用传递的int的副本.
  4. 然后函数返回,但由于没有变量记录了从new返回的指针,没有任何东西可以释放内存.必须通过删除镜像每个新的,以便销毁对象并释放其内存.
  5. 因此内存泄漏