我在C ++上偶然发现了这个问题,但完全不知道它是怎么发生的,请查看下面的代码片段:
int main() {
int *aptr = new int(20); //Declare an integer space with 20, and aptr points to it
shared_ptr<int> a(aptr); //Declare a shared_ptr to points where aptr points
stringstream ss;
ss << a;
const char *chstr = ss.str().c_str(); // Save the address as string
void *address;
sscanf(chstr, "%p", (void **)&address); // Convert string back to pointer
a = NULL; // Free the shared pointer
cout << *reinterpret_cast<int*>(address) << endl; // Output: 0, 20 has gone
return 0;
}
有没有人可以告诉我为什么地址已被释放?
我没有操纵原始的整数指针“aptr”,但是因为shared_ptr,所以它的空间已经消失了。
我想知道它是怎么发生的,谢谢大家!
答案 0 :(得分:7)
A 1.48 2.64 1.02 2.46 2.73
C 3.76 2.07 4.61 2.26 2.05
背后的全部目的是取得动态分配对象的所有权。一旦std::shared_ptr
获得动态分配的对象的所有权,通过std::shared_ptr
或直接指定它,std::make_shared
拥有它,锁定库存和桶。拥有它意味着当对动态范围对象的最后一次引用超出范围时,自动std::shared_ptr
动态范围对象。这就是delete
的用途,而不是别的。
shared_ptr
这使用a = NULL;
的赋值运算符来替换shared_ptr
拥有的指针(*)。由于shared_ptr
拥有的原始动态范围对象没有其他引用,shared_ptr
shared_ptr
是用于构造它的原始指针。
您仍然拥有指向delete
的原始本机指针这一事实无关紧要。 int
并不关心。整件事情得到shared_ptr
d。
如果您不希望delete
shared_ptr
delete
new
,并使用原生指针,请不要使用shared_ptr
,或确保只要你仍然需要使用指向底层对象的本机指针,一个仍然存在。
(*)这实际上隐含地构造了另一个shared_ptr
,并使用了常规赋值运算符。
答案 1 :(得分:1)
此代码无法在g ++ 4.2.1中编译(但正如Sam所提到的,它符合版本6):
Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall main.cpp
main.cpp:17:11: error: no viable overloaded '='
a = NULL; // Free the shared pointer
~ ^ ~~~~
顺便说一句,你应该使用shared_ptr::reset
:
在所有其他情况下,shared_ptr通过use获取p的所有权 计数为1,并且 - 最后 - 使用del和/或alloc作为删除和 分配器。
此外,对此功能的调用具有相同的副作用 shared_ptr的析构函数在其值更改之前被调用(包括 如果此shared_ptr是唯一的,则删除托管对象。
同时检查string::c_str
。您正在保存临时字符串的地址,这是不好的开始。