【问题标题】:initializing a shared pointer with a static or global object使用静态或全局对象初始化共享指针
【发布时间】:2018-12-01 21:38:25
【问题描述】:

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

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 教程中看到了以下代码 sn-p (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 是一个全局变量或静态变量。不是吗?当上面的流共享指针超出范围时,为什么它不会造成被破坏的风险。 请阐明一些观点。 谢谢

【问题讨论】:

  • 您的问题的答案就在代码中:“我们必须提供一个空的删除器以避免破坏全局流对象”
  • 谢谢。当我在 boost 中检查 null_deleter 时,它是一个结构,其操作符 () 实现如下。模板 void operator() (T*) const BOOST_NOEXCEPT {} 。您能否解释一下为什么在上面的代码中可以通过调用 boost::null_deleter() 来启动结构的实例,而不是仅仅将结构本身作为 boost::null_deleter 提供,它在共享指针初始化中接受 lambda
  • 这叫做函子
  • 请不要在 cmets 中提问或添加信息,而是编辑您的问题。 null_deleter 只是一个空操作。它什么也没做。因此,当共享指针计数器变为 0 时,std::clog 不会被删除。
  • 为什么首先要将指向全局对象的指针存储在shared_ptr 中? shared_ptr 用于共享所有权,全局变量不归任何人所有,无论如何都是“共享”的

标签: c++ shared-ptr


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

      有两种选择:

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

      2. 使用别名构造函数。 std::weak_ptrs 无法使用它。
        请参阅“Using C++ shared pointer's aliasing constructor with an empty shared pointer”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-03
        相关资源
        最近更新 更多