复制boost :: shared_ptr

时间:2013-05-07 16:07:17

标签: c++ boost shared-ptr

typedef boost::shared_ptr<SomeData> data_ptr;
data_ptr cached_ptr;   // class member 
bool someWork(data_ptr& passed_ptr)
{
  // must copy passed_ptr = cached_ptr under some conditions
  // without pointing at the same memory 
  // I saw somewhere that I should do 
  // passed_ptr.reset(new SomeData(???))
  // I don't have a "reset" on passed_ptr
}

我查看了文档;

复制和转换构造函数

shared_ptr(shared_ptr const & r); // never throws
template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws
Requires: Y* should be convertible to T*.

Effects: If r is empty, constructs an empty shared_ptr; otherwise,
         constructs a shared_ptr that shares ownership with r.

我不知道它是如何运作的 - 是这样的吗?

passed_ptr = shared_ptr(cached_ptr);

? const会去哪里?他们分享所有权意味着什么?那么它不是副本,如果我修改“pass_ptr”,更改会影响“cached_ptr”吗?

我找不到例子......请帮助。

谢谢。

3 个答案:

答案 0 :(得分:12)

好吧,如果你有shared_ptr并将它分配给另一个shared_ptr,那么这两个共享指针将共享该对象的所有权 - 这意味着指向对象所有权的引用计数将是增加了一个。

实际上,在上面的行中,您根本不需要构造临时共享指针。这就足够了:

passed_ptr = cached_ptr;

无论如何,复制构造一个shared_ptr基本上遵循相同的逻辑:你从一个共享指针开始,最后你得到两个共同拥有同一个对象的共享指针(意味着该对象将被销毁)只有当那些共享指针的两个都被破坏时才会被破坏。所以当你这样做时:

passed_ptr = shared_ptr(cached_ptr);

实际上你从给定对象的一个​​共享指针(cached_ptr)开始,然后创建一个临时指针(将引用计数带到2),然后将其分配给passed_ptr(带来引用计数为3),并最终被销毁(将引用计数返回到2)。

另一方面,如果你想要的是passed_ptr作为cached_ptr指向的对象的副本的共享指针,那么你应该而不是(假设Data是可复制的,当然):

passed_ptr = boost::make_shared<Data>(*cached_ptr);

或者,或者:

passed_ptr.reset(new Data(*cached_ptr));

答案 1 :(得分:9)

好。让我们看看我们是否可以谈论这个问题。

std::shared_ptr<Data> x = std::make_shared<Data>();
std::shared_ptr<Data> y = x;

assert(x.get() == y.get());

如果我更改了x指向的内容,那么这也会改变有关y的信息。因为他们指的是同一件事。

x->member = 3;
assert(x->member == 3);
assert(y->member == 3);

我可以更改x指向的内容而不更改y指向的内容。

x = std::make_shared<Data>();
assert(x.get() != y.get());

如果我这样做,则x的更改不会反映在y中。因为他们指的是不同的东西。

x->member = 4;
assert(x->member == 4);
assert(y->member != 4);

如果我要复制x的内容,并将其存储在y中,那么我需要创建一个新的共享对象。

y = std::make_shared<Data>(*x);

此时,xy都将该成员变量设置为4.因为x设置了它,我们创建了*y,内容为{ {1}}。

*x

但是,因为assert(x->member == 4); assert(y->member == 4); x指向内存中的不同内容,我们可以更改其中一个。

y

如果我要将shared_ptr传递给函数,那就像第一种情况一样。

assert(x.get() != y.get();
x->member = 3;
assert(x->member == 3);
assert(y->member == 4);

我还可以使用void func(std::shared_ptr<Data> z) { assert(x.get() == z.get()); } func(x); 释放特定shared_ptr的内容。这将导致shared_ptr指向的值变为NULL。

reset()

关于const正确性,这有点奇怪。

x.reset();
assert(x.get() == NULL);

答案 2 :(得分:1)

通常的惯例是传递const shared_ptr

bool
someWork( data_ptr const& passed_ptr )
{
    //  ...
}

这允许使用指针(包括复制和转换) 它),但不修改它。

如果要更改指针在呼叫时指向的内容 站点,然后你必须传递一个非const引用。最简单的 这里的政策是,恕我直言,为它分配新的价值,但你可以 也可以调用reset函数。

关于它是如何工作的:当你将指针传递给引用时 参数,你只需给被调用的函数访问 原始指针。在引擎盖下,它非常像 一个系统地解引用的指针。而你似乎 将指针与指向的内容混淆;它是什么 指向的是共享,而不是指针本身。指针本身 行为与任何其他C ++对象完全相同。