交换 2 shared_ptr的内容

swap the content of 2 shared_ptr

提问人:Thinium 提问时间:10/19/2023 最后编辑:Remy LebeauThinium 更新时间:10/19/2023 访问量:68

问:

交换两个 s 的内容时,仅交换内容。当在交换之前从另一个副本创建时,我很惊讶新副本的内容保持不变。shared_ptrshared_ptrshared_ptr

下面是一个示例:

std::shared_ptr<int> foo (new int(10));
std::shared_ptr<int> bar (new int(20));

auto abc = foo;
std::swap (foo, bar);
std::cout << "foo: " << *foo << '\n';
std::cout << "bar: " << *bar << '\n';
std::cout << "abc: " << *abc << '\n';

它打印:

foo: 20
bar: 10
abc: 10

为什么在这种情况下不是 20?鉴于它是 .abcfoo

C++ 共享 PTR

评论

0赞 463035818_is_not_an_ai 10/19/2023
“交换两个共享指针的内容时,只交换内容。”错字?
0赞 463035818_is_not_an_ai 10/19/2023
你期望什么输出?
3赞 François Andrieux 10/19/2023
abc是交换前的副本。交换对象不会同时交换该对象的先前副本。您可能会混淆代码(交换每个指针指向的内容)和(交换指向的值)。foostd::swap(*foo, *bar);
1赞 463035818_is_not_an_ai 10/19/2023
毕竟,共享指针只是一个指针(好吧,它更多,但它仍然对指针进行建模),并且交换两个指针不会影响指向相同对象的其他 poitner。
0赞 n. m. could be an AI 10/19/2023
“ABC 现在是 Foo 的副本”与“ABC 现在是并且永远是 Foo 的副本”有很大不同。赋值是第一件事。为了做第二件事,你需要魔法。

答:

2赞 463035818_is_not_an_ai 10/19/2023 #1

交换两个shared_ptrs,....的内容时

这不是你的代码所做的事情。 交换指针。它不会交换指尖。如果要交换内容,则需要交换内容:。std::swap(foo,bar)std::swap(*foo,*bar)


事实上,它是智能指针,它实际上与您的代码无关。此外,动态分配变化不大,因此我们可以使用一个更简单的示例来说明:

int a = 10;
int b = 20;

int* a_ptr = &a;
int* b_ptr = &b;

int* c_ptr = a_ptr;

到目前为止,您有两个指针,分别指向 和 。 是 和 也指向的副本。a_ptrb_ptrabc_ptra_ptra

std::swap (a_ptr,b_ptr);

交换后,您现在指向并指向 .第三个指针不受此影响。它仍然指向 .也,并且没有被修改。a_ptrb_ptra_ptrbb_ptrac_ptraab

std::cout << "foo: " << *a_ptr << '\n';
std::cout << "bar: " << *b_ptr << '\n';
std::cout << "abc: " << *c_ptr << '\n';

输出将是:

20
10
10

就像在您的代码中一样。

6赞 Remy Lebeau 10/19/2023 #2

shared_ptr只是指向数据的指针。您不是在交换数据本身,而是在交换指针。

让我们一步一步地看一下:

std::shared_ptr<int> foo (new int(10));
std::shared_ptr<int> bar (new int(20));

在这些语句之后,您有两个指向两个单独分配的指针:int

[ foo ] ---> [10]
[ bar ] ---> [20]
auto abc = foo;

然后,此语句创建指向的同一分配。因此,在交换之前,您现在拥有:abcintfoo

[ foo ] -+-> [10]
         |
[ abc ] -+

[ bar ] ---> [20]
std::swap (foo, bar);

然后,您正在交换 和 持有的指针,但您将指针单独保留。因此,在交换之后,您现在拥有:foobarabc

    +---------------+
    |               |
[ foo ]  +-> [10]   |
         |          |
[ abc ] -+          |
         |          |
[ bar ] -+   [20] <-+

这就是为什么打印 20、打印 10 和打印 10 的原因。*foo*bar*abc