gpt4 book ai didi

c++ - 将 shared_ptr 的嵌套智能指针重置为 shared_ptr(或 unique_ptr),看似矛盾

转载 作者:行者123 更新时间:2023-11-30 01:50:58 25 4
gpt4 key购买 nike

我知道由 std::shared_ptr 管理的对象不是 delete d by reset()除非它是唯一的 shared_ptr在那个时候管理它。我知道当有多个 shared_ptr s managing the same object, managed object's value changes are reflected through shared_ptr就是指向它,同时更改其中任何一项 shared_ptr的值(不是其托管对象的值)由 reset() 引起调整它(即将 shared_ptr 从指向原始托管对象的一个​​更改为指向任何内容或其他内容的一个)不会更改另一个 shared_ptr s的值(即都指向原来的托管对象,原来的托管对象仍然存在):

#include <memory>
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<shared_ptr<int>> vec{ make_shared<int>(5) };
shared_ptr<int> sptr(vec[0]);
++ *sptr;
cout << *vec[0] << endl; // 6
vec[0].reset();
vec.pop_back();
cout << *sptr << endl; // 6
}

但是当使用两个间接级别时,我就失去了这种逻辑。给定一个名为 Wrapper 的类和一个 shared_ptr<shared_ptr<Wrapper>>和任意数量的其他 shared_ptr<shared_ptr<Wrapper>> s初始化为之前的,为什么这个配置允许一个reset()调用任何内部 shared_ptr有效reset()所有其他内部 shared_ptr是吗?

我的猜测是:任何outer shared_ptr 的托管对象s 是内部 shared_ptr (不是 Wrapper )并更改内部 shared_ptr 的值(通过 reset() 调整内部 shared_ptr ,这将内部 shared_ptr 的值从指向 Wrapper 实例的值更改为指向任何内容的实例)反射(reflect)在所有 outshared_ptr s,有效地导致所有 outer shared_ptr s 失去对 Wrapper 的间接管理实例,从而删除 Wrapper实例。

但按照同样的逻辑,重置内部指针之一不会导致该特定内部指针失去对 Wrapper 的管理权吗? ?鉴于所有其他外部指针都指向它们自己的内部指针(即用它们构造的内部指针),那些外部指针不会继续对 Wrapper 进行间接管理吗? ,因为重置一个内部指针不会改变 Wrapper的值,其他内部指针应该仍然可以访问它吗?这对我来说是个悖论。

如果重置一个内部指针会有效地重置所有内部指针,那么这意味着内部指针的 use_count()1就在 reset() 之前.我想到的唯一方法是多个shared_ptr s 可以出现 来管理同一个对象,同时保持 use_count()1将是通过幻觉:他们管理具有相同值的不同对象(即不同地址的对象)。我通过制作 int 来测试这个包装器名为 Wrapper ,其唯一的数据成员是包装的 int和一个 static instance_count跟踪 Wrapper 的数量当前存在的实例。

struct Wrapper {
Wrapper(int par = 0) : num(par) { ++instance_count; }
Wrapper(const Wrapper& src) : num(src.num) { ++instance_count; }
~Wrapper() { --instance_count; }
int num;
static int instance_count;
};
int Wrapper::instance_count = 0;

int main() {
shared_ptr<shared_ptr<Wrapper>> dual_ptr_1(
make_shared<shared_ptr<Wrapper>>(
make_shared<Wrapper>(Wrapper(5))
)
);
// - Output -
cout << Wrapper::instance_count << endl; // 1
shared_ptr<shared_ptr<Wrapper>> dual_ptr_2(dual_ptr_1);
cout << Wrapper::instance_count << endl; // 1
cout << dual_ptr_1->use_count() << endl; // 1
cout << dual_ptr_2->use_count() << endl; // 1
cout << dual_ptr_1.use_count() << endl; // 2
cout << dual_ptr_2.use_count() << endl; // 2
// note that above, the '->' operator accesses
// inner ptr while '.' operator is for outer ptr
cout << (*dual_ptr_1)->num << endl; // 5
cout << (*dual_ptr_2)->num << endl; // 5
dual_ptr_2->reset();
cout << Wrapper::instance_count << endl; // 0
cout << dual_ptr_1->use_count() << endl; // 0
cout << dual_ptr_2->use_count() << endl; // 0
cout << dual_ptr_1.use_count() << endl; // 2
cout << dual_ptr_2.use_count() << endl; // 2
}

显然有 2指向 1 的内部指针Wrapper目的;内部指针的 use_count最多是1 (销毁前); Wrapper类(class)的instance_count最多是1 (销毁前);和间接管理的Wrapper对象可以通过两个外部指针访问(这意味着两个外部指针都没有被另一个移动构造);并重置一个内部指针有效地重置了所有这些指针;所以我还是不明白这个看似矛盾的现象。

我也在这篇文章中就上述代码具有内部 shared_ptr 的情况提出了同样的问题。 s 替换为 unique_ptr s,内部make_shared替换为 make_unique , 和 use_count()注释掉内部指针(因为 unique_ptr 缺少该方法),它提供相同的输出。这对我来说似乎是个悖论,因为 unique_ptr s 在这里似乎并不独特。

最佳答案

Given a class named Wrapper and a shared_ptr<shared_ptr<Wrapper>> and any number of other shared_ptr<shared_ptr<Wrapper>>s initialized to the prior, why does this configuration allow a reset() called on any inner shared_ptr to effectively reset() all other inner shared_ptrs?

没有其他内在shared_ptr s,你有一个包含对象的实例,即

dual_ptr_1
\
--> shared_ptr --> Wrapper
/
dual_ptr_2

而不是

dual_ptr_1 --> shared_ptr 
\
--> Wrapper
/
dual_ptr_2 --> shared_ptr

在您调用 dual_ptr_2->reset(); 之后这改变为

dual_ptr_1
\
--> shared_ptr --> (empty)
/
dual_ptr_2

关于c++ - 将 shared_ptr 的嵌套智能指针重置为 shared_ptr(或 unique_ptr),看似矛盾,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26748634/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com