C++ 为什么共享指针在修改后会失效?

C++ 为什么共享指针在修改后会失效?,c++,shared-ptr,C++,Shared Ptr,根据Herb Sutter在中的谈话,一个共享的\u ptr应该在修改后失效 auto sv = make_shared<vector<int>>(100); shared_ptr<vector<int>>* sv2 = &sv; vector<int>* vec = &*sv; int* ptr = &(*sv)[0]; *ptr = 1 ; vec->push_back(2); //A:

根据Herb Sutter在中的谈话,一个
共享的\u ptr
应该在修改后失效

auto sv = make_shared<vector<int>>(100);
shared_ptr<vector<int>>* sv2 = &sv;
vector<int>* vec = &*sv;
int* ptr = &(*sv)[0];
*ptr = 1 ;

vec->push_back(2);        //A: modification
*ptr = 5;                 //Error: ptr was invalidated by "push_back" on line A

ptr = &(*sv)[0];
(*sv2).reset();            //B: modification
vec->push_back(6);         //Error: vec was invalidated by "reset" on line B
auto sv=make_shared(100);
共享_ptr*sv2=&sv;
向量*vec=&*sv;
int*ptr=&(*sv)[0];
*ptr=1;
vec->推回(2)//A:修改
*ptr=5//错误:ptr因A行上的“向后推”而无效
ptr=&(*sv)[0];
(*sv2.reset()//B:修改
vec->推回(6)//错误:第B行的“重置”使vec无效
我的编译器没有捕捉到这些错误。无论如何,我们使用智能指针来防止内存泄漏。禁止修改
共享\u ptr
的原因是什么?为了避免意外?如果是这样的话,我们就不能把它声明为
const
?另一方面,如果由于
共享\u ptr
而无法应用对
向量的许多操作,这不是很不方便吗


在阅读了这些评论之后,现在我开始理解它在这里的真正作用。修改
共享\u ptr
会使指向它的其他原始指针无效


正如dyp在评论中指出的那样,
push_back
可能会重新分配,这可能会使
ptr
无效。如果它没有重新分配,
ptr
是否仍然有效?如果它真的进行了重新分配,那么如果编译器只是将其所有伙伴带到新的领域,比如,为这些原始指针分配新的地址,岂不是更简单、更具建设性吗?

在更大的背景下,赫伯在为2015年CPPCon做广告(他不是唯一一个)

他试图指出的一点是,根据标准,存在完全合法的代码,但通过静态分析,我们可以看出这是有问题的

在这里给出的示例中,我们有一个
共享ptr
向量
,然后是指向该指针的原始指针,然后是指向共享指针持有的向量的原始指针,甚至是指向共享指针持有的向量内的元素的原始指针

然后他做了一系列会导致未定义行为的事情。这些调用是完全合法的(在
共享\u ptr
上重置调用,然后尝试在
向量上执行操作),但是在更大的背景下,他认为编译器应该能够告诉您(通过静态分析)您做了一件坏事

因此,在视频中,你会看到他做了这些现代编译器无法捕捉到的坏事,然后演示了一个充满GSL的编译器(在本例中是Visual Studio 2015)将如何捕捉它们


这次谈话内容丰富,同样具有政治性。之所以使用VisualStudio,可能是因为赫伯本人是微软的员工;人们普遍认为VisualStudio是一个很棒的IDE,我认为,要想带走的信息是,微软确实致力于C++,尽管近年来有许多动作表明了对C语言的更高承诺,这让C++开发者感觉像是二等公民。

你能指出他在视频里说的是什么吗?<代码> VEC> PuthSubBuff[/Cord]可以重新分配,在这种情况下,指针进入旧的分配变得无效。示例A中的
ptr
就是这种情况。类似地,如果重置
shared\u ptr
并且它是向量的唯一所有者,那么该向量将被销毁,指向(和进入)该向量的指针将无效。示例B中的
vec
就是这种情况。进一步减少代码,您可以简单地使用带有自动存储的向量演示悬空指针。我不明白这里有什么奇怪的地方。vec是一个原始指针,在sv2重置后它会挂起。UlrichEckhardt说了什么。除了(*sv2).reset(),您实际上并没有修改共享的\u ptr,代码所做的只是修改原始指针。一旦sv shared_ptr被(*sv2).reset()重置,原始指针ptr和vec就变成了悬空指针,这会导致未定义的行为。我已经观看了讨论,Herb Sutter没有任何地方声称应该使共享指针无效。到底是什么让你认为他是这样的?在录像的什么时候发生?在我看来,这部分谈话的重点是,编译器在理论上是如何捕捉这些错误的,因为代码分析工具可以捕捉它们;也许智能指针的存在并不能神奇地消除所有错误。