关于智能指针范围的困惑

时间:2019-08-29 17:45:07

标签: c++ c++11 scope smart-pointers

假设我对某些假设类Obj具有以下功能,该类可以容纳指向类型Foo的对象的(智能)指针:

class Obj {
  public:
    void setFoo(std::shared_ptr<Foo>);
    std::shared_ptr<Foo> foo;
};

Obj::setFoo(std::shared_ptr<Foo> fooPtr) {
  foo = fooPtr;
}

Obj* getObj() {
  std::shared_ptr<Foo> fooPtr = std::make_shared<Foo>(new Foo());
  Obj *obj = new Obj();
  obj->setFoo(fooPtr);
  return obj; 
}

何时将删除我的智能指针?

  1. 当我们从getObj返回时,因为它不在函数的作用范围内,并且obj未被“聪明”地指出了吗?
  2. 以后何时在我的程序中删除obj吗?

我的测试让我认为它是2.,但是一位同事认为这是1。

我找不到能回答我问题的文档,因为我阅读的所有智能指针的解释都不能使指针脱离其创建者的范围...

2 个答案:

答案 0 :(得分:2)

fooPtr的末尾,分配并保存在getObj() 内的指针不会被破坏,因为在setFoo()之后,两个< / strong>包含它的共享指针。

getObj()的末尾,第一个包含共享指针的被销毁(fooPtr),但另一个幸存了:foo对象的Obj成员由obj

objgetObj()返回,因此第二个共享指针在getObj()的末尾保留。

答案 1 :(得分:2)

请注意,std::make_shared<Foo>(new Foo())是反模式。如果std::make_shared引发异常(例如std::bad_alloc)或Foo调用的std::make_shared<Foo>构造函数引发异常,则new Foo()的结果永远不会被删除,因此会泄漏内存

此外,obj没有使用智能指针进行管理,因此可能会泄漏。

更安全的版本:

struct Foo {};

class Obj : std::enable_shared_from_this<Obj> {
    Foo foo;
public:
    void setFoo(Foo const& f) {
        foo = f;
    }

    std::shared_ptr<Foo> getFoo() {
        return std::shared_ptr<Foo>(this->shared_from_this(), &foo); // aliasing constructor.
    }
};

std::shared_ptr<Obj> getObj() {
    auto obj = std::make_shared<Obj>();
    // obj->setFoo(Foo(<args>); // if necessary
    return obj;
}

int main() {
    std::shared_ptr<Obj> obj = getObj();
    std::shared_ptr<Foo> foo = obj->getFoo();
}

请注意,由于使用了obj别名构造函数,因此共享指针fooObj都引用相同的基础对象std::shared_ptr。通过std::shared_ptr管理对象后,您可以为其成员创建std::shared_ptr,而不必将这些成员变成std::shared_ptr