将shared_ptr与const引用

时间:2017-06-30 23:06:16

标签: c++ c++14 shared-ptr

我需要创建几个Worker类,这些类具有指向主程序所拥有的Object的指针。这是在C ++ 14

由于原因,Object必须符合某些条件 - 它必须有一个已删除的默认构造函数,它是不可复制的,不可移动的。我需要使用智能指针。

主程序将拥有Object。每个工人阶级都需要从中读取内容

class Object
{
  Object() = delete;
  ~Object();

  // Non copyable
  Object(const Object &other) = delete;
  Object &operator=(const Object &other) = delete;

  // Non movable
  Object(Object &&other) = delete;
  Object &operator=(Object &&other) = delete;

  // Constructor
  explicit Object(double threshold);
};

class Worker
{
public:
  void initialize(const Object& obj)
  {
    // Option 1 - errors out, complains its non copyable
    object_ptr = std::make_shared<const Object>(obj);

    // Option 2
    object_ptr = std::shared_ptr<const Object>(&obj);

    // Option 3
    object_ptr = std::shared_ptr<const Object>(&obj, [](const Object*){});
  }

  void doSomething();

private:
  std::shared_ptr<const Object> object_ptr;
};

int main () 
{
  Object object;

  Worker worker1;
  Worker worker2;

  worker1.initialize(object);
  worker2.initialize(object);

  while(1)
  {
    // Main does stuff to Object

    worker1.doSomething();
    worker2.doSomething();
  }

  return 0;
}

Worker内初始化指针的最佳方法是什么?

2 个答案:

答案 0 :(得分:0)

我个人会这样做

class Worker
{
public:
    void initialize(const Object& obj)
    {
        object_ptr = &obj;
    }
private:
    const Object* object_ptr = nullptr;
};

原始指针表示非所有权,这正是情况所在。

如果必须使用shared_ptr,则无法将一个作为参数传入,shared_ptr与其关联的数据多于托管对象。

class Worker
{
public:
    void initialize(std::shared_ptr<const Object> p)
    {
        swap(object_ptr, p);
    }
private:
    std::shared_ptr<const Object> object_ptr;
};

int main()
{
    auto obj = std::make_shared<const Object>();
    //...
}

shared_ptr表示其内容:资源共享。传递shared_ptr是为了宣称有多个所有者,并且资源对所有人都是通用的,也就是说资源必须比任何资源都长。

请注意您如何在堆栈上使用 (或者更确切地说,具有自动存储持续时间),这表明此资源实际上并非由工作人员拥有。根据工人的定义,我们自动知道该对象将比工人更长,这远远优于使用shared_ptr

答案 1 :(得分:-2)

为什么不使用shared_ptr的aliasing constructor

template< class Y > 
shared_ptr( const shared_ptr<Y>& r, element_type* ptr ) noexcept; 

这允许您创建shared_ptr,但实际上并不拥有该对象,因此存储的值实际上不是引用计数。这意味着引用的对象必须在外部保持有效。

在这种情况下,只需将initialize设置为:

void initialize(const Object& obj)
  {
    typedef std::shared_ptr<const Object> my_ptr;
    object_ptr = my_ptr(my_ptr(), &obj);
  }

这是一个黑客攻击,它会伪造一个真正的shared_ptr,但它会起作用。对于自包含的外部示例,请尝试:

#include <memory>

struct x_t
{
    x_t() = delete;
    x_t(const x_t&) = delete;
    x_t(x_t&&) = delete;
    x_t(double y) {}
};

int main()
{
    typedef std::shared_ptr<const x_t> x_t_ptr;
    const x_t x(5);

    x_t_ptr ptr = x_t_ptr(x_t_ptr(), &x);

    return 0;
}

我应该警告你,你不应该这样做,因为当你没有这样的东西时,你似乎有记忆安全。基本上,您可以保证您具有内存安全性,同时有效地使用指向临时对象的原始指针。这非常危险。