以下代码显示使用全局或静态对象的地址初始化共享对象不正确,因为当共享指针超出范围时,将删除全局对象。
class Dog() {
public:
void bark() {
cout << "Dog barks" << endl;
}
};
Dog g_Dog;
void test() {
shared_ptr<Dog> myDog(&g_Dog);
myDog->bark();
}
int main() {
test();
}
以上代码崩溃。我的理解是我们不应使用静态或全局对象初始化共享指针,而应仅使用堆中的对象初始化共享指针。那是正确的吗?
我在Boost Log教程中看到了以下代码片段 (https://www.boost.org/doc/libs/develop/libs/log/doc/html/log/tutorial/sinks.html)
#include <boost/core/null_deleter.hpp>
// We have to provide an empty deleter to avoid destroying the global stream object
boost::shared_ptr< std::ostream > stream(&std::clog, boost::null_deleter());
sink->locked_backend()->add_stream(stream);
你们能解释为什么代码
boost::shared_ptr< std::ostream > stream(&std::clog, boost::null_deleter());
不会造成任何问题。它看起来像std :: clog是一个整体或静态变量。是不是当上述流共享指针超出范围时,为什么不构成被销毁的风险? 请说明一下。 谢谢
答案 0 :(得分:1)
通过链接null_deleter:boost :: null_deleter函数对象可以用作带有智能指针(例如unique_ptr或shared_ptr)的删除器。删除器对释放后提供的指针不执行任何操作,这在将指向对象释放到其他位置时非常有用。
换句话说,使用null_deleter,智能指针将永远不会尝试删除指向的对象。
答案 1 :(得分:0)
如果您提供一个不会试图销毁并释放它的删除器,那是合法的。
shared_ptr
接受两个参数(检查documentation):地址和删除器。 Deleter参数是可选的。
默认的删除器(即,当您不明确提供删除器时使用的删除器)会破坏对象并释放堆,因此它显然不适用于堆上没有的任何东西。
答案 2 :(得分:0)
有两种选择:
使用nop-deleter。只需接受该虚假控制块的开销即可。
使用别名构造函数。 std::weak_ptr
s不能使用。
请参阅“ Using C++ shared pointer's aliasing constructor with an empty shared pointer ”。