使用静态或全局对象初始化共享指针

initializing a shared pointer with a static or global object

以下代码显示使用全局或静态对象的地址初始化共享对象是不正确的,因为当共享指针超出范围时全局对象将被删除。

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 日志教程中看到了以下代码片段 (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 是全局变量或静态变量。不是吗?当上述流共享指针超出范围时,为什么它不构成被破坏的风险。 请说明一下。 谢谢

来自link null_deleter: boost::null_deleter 函数对象可以用作具有智能指针的删除器,例如unique_ptr 或shared_ptr。删除器不会对释放时提供的指针做任何事情,这使得它在指向的对象被释放到别处时很有用。

换句话说,使用null_deleter,智能指针永远不会尝试删除指向的对象。

如果您提供一个不会试图销毁和释放它的删除器,这是合法的。

shared_ptr 有两个参数(检查 documentation):地址和删除器。删除参数是可选的。

默认的删除器(即当您没有明确提供任何内容时使用的删除器)会销毁对象并释放堆,因此它显然不会对不在堆上的任何内容起作用。

有两种选择:

  1. 使用 nop 删除器。只接受那个虚假控制块的开销。

  2. 使用别名构造函数。 std::weak_ptrs 将无法使用它。
    参见“”。