5
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 会去哪里?他们共享所有权意味着什么?那么它不是副本,如果我修改“passed_ptr”,更改会影响“cached_ptr”吗?

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

谢谢你。

4

3 回答 3

12

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

事实上,在上面一行中,你根本不需要构造一个临时共享指针。这就够了:

passed_ptr = cached_ptr;

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

passed_ptr = shared_ptr(cached_ptr);

cached_ptr实际上,您从一个指向给定对象的共享指针passed_ptr(引用计数回到 2)。

另一方面,如果您想要拥有一个指向 指向的对象副本passed_ptr的共享指针,那么您应该这样做(当然,假设是可复制的):cached_ptrData

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

或者,或者:

passed_ptr.reset(new Data(*cached_ptr));
于 2013-05-07T16:16:30.523 回答
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使用*x.

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

但是,因为xy指向内存中的不同事物,我们可以更改其中之一。

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

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

void func(std::shared_ptr<Data> z) {
    assert(x.get() == z.get());
}

func(x);

我还可以通过使用来释放特定 shared_ptr 的内容reset()。这将导致 shared_ptr 指向的值变为 NULL。

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

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

const std::shared_ptr<Data> x;
x.reset(); // Fails because the shared_ptr is const.
x->member = 3; // Succeeds because Data is not const.

std::shared_ptr<const Data> x;
x.reset(); // Succeeds because the shared_ptr is not const.
x->member = 3; // Fails because Data is const.
于 2013-05-07T16:15:54.460 回答
1

通常的约定是传递一个 const shared_ptr

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

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

如果要更改指针在调用站点指向的内容,则必须传递非常量引用。恕我直言,这里最简单的策略是为其分配新值,但您也可以调用该reset函数。

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

于 2013-05-07T16:14:56.910 回答