在C++ 11中,可以使用shared_ptr<>
与对象或变量建立所有权关系,并使用weak_ptr<>
以非所有权方式安全地引用该对象。
您还可以使用unique_ptr<>
与对象或变量建立所有权关系。但是,如果其他非拥有对象也要引用该对象怎么办? weak_ptr<>
在这种情况下没有帮助。原始指针很有帮助,但会带来各种不利影响(例如,它们可能是automatically initialized to nullptr,但这是通过与std::*_ptr<>
类型不一致的技术来实现的)。
对于通过weak_ptr<>
拥有的对象的非所有者引用,相当于unique_ptr<>
吗?
这是一个澄清的示例,类似于我正在开发的游戏中的某些内容。
class World
{
public:
Trebuchet* trebuchet() const { return m_trebuchet.get(); }
private:
std::unique_ptr< Trebuchet > m_trebuchet;
};
class Victim
{
public:
Victim( Trebuchet* theTrebuchet ) : m_trebuchet( theTrebuchet ) {}
~Victim()
{
delete m_trebuchet; // Duh. Oops. Dumb error. Nice if the compiler helped prevent this.
}
private:
Trebuchet* m_trebuchet; // Non-owning.
};
shared_ptr< Victim > createVictim( World& world )
{
return make_shared< Victim >( world.trebuchet() );
}
在这里,我们使用原始指针来维护与其他位置通过
unique_ptr<>
拥有的对象的非所有者关系。但是我们能做的最好的是原始的吗?希望是一种指针:
std::raw_ptr<T>
。 _ptr<
(大致)找到所有指针。 从而:
int* p; // Unknown value.
std::raw_ptr< int > p; // null.
这种类型现在已经在C++中存在了吗?是为将来提出的?还是在例如促进?
最佳答案
shared_ptr
的“通知”行为要求对引用计数控制块进行引用计数。 shared_ptr
的引用计数控制块为此使用了单独的引用计数。 weak_ptr
实例维护对此块的引用,而weak_ptr
本身可以防止对引用计数控制块进行delete
ed。当强计数变为零时,指向对象的析构函数将被调用(这可能会或可能不会导致存储该对象的内存的delete
ion),并且仅当弱引用计数变为零时,控制块才会被delete
ed归零。unique_ptr
的宗旨是在普通指针上的开销为零。分配和维护引用计数控制块(以支持weak_ptr
-ish语义)打破了这一宗旨。如果您需要该描述的行为,那么即使没有对该对象的其他引用,也确实需要共享语义。在这种情况下,仍然需要进行共享-共享对象是否已销毁的状态。
如果您需要通用的非所有者引用并且不需要通知,请使用普通指针或unique_ptr
中对该项目的普通引用。
编辑:
在您的示例中,看起来Victim
应该请求Trebuchet&
而不是Trebuchet*
。然后很明显,谁拥有相关对象。
class World
{
public:
Trebuchet& trebuchet() const { return *m_trebuchet.get(); }
private:
std::unique_ptr< Trebuchet > m_trebuchet;
};
class Victim
{
public:
Victim( Trebuchet& theTrebuchet ) : m_trebuchet( theTrebuchet ) {}
~Victim()
{
delete m_trebuchet; // Compiler error. :)
}
private:
Trebuchet& m_trebuchet; // Non-owning.
};
shared_ptr< Victim > createVictim( World& world )
{
return make_shared< Victim >( world.trebuchet() );
}
关于c++ - shared_ptr <>指向weak_ptr <>,就像unique_ptr <>指向…是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17536731/