假设我对某些假设类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;
}
何时将删除我的智能指针?
getObj
返回时,因为它不在函数的作用范围内,并且obj
未被“聪明”地指出了吗?obj
吗?我的测试让我认为它是2.,但是一位同事认为这是1。
我找不到能回答我问题的文档,因为我阅读的所有智能指针的解释都不能使指针脱离其创建者的范围...
答案 0 :(得分:2)
在fooPtr
的末尾,分配并保存在getObj()
内的指针不会被破坏,因为在setFoo()
之后,两个< / strong>包含它的共享指针。
在getObj()
的末尾,第一个包含共享指针的被销毁(fooPtr
),但另一个幸存了:foo
对象的Obj
成员由obj
。
obj
由getObj()
返回,因此第二个共享指针在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
别名构造函数,因此共享指针foo
和Obj
都引用相同的基础对象std::shared_ptr
。通过std::shared_ptr
管理对象后,您可以为其成员创建std::shared_ptr
,而不必将这些成员变成std::shared_ptr
。