在试验this question时,我创造了一个我完全不明白的例子。特别是,它突出了我对指针,引用和boost :: shared_ptr。
的误解int& r = *(new int(0));//gratuitous pointer leak, got to initialize it to something
{
boost::shared_ptr<int> sp(new int(100));
r = *sp;
cout << "r=" << r << endl;
}
cout << "r=" << r << endl << endl;
int* p;
{
boost::shared_ptr<int> sp(new int(100));
p = &*sp;
cout << "*p=" << *p << endl;
}
cout << "*p=" << *p << endl;
运行此代码会得到如下输出:
r=100
r=100
*p=100
*p=13
为什么引用会在shared_ptr死亡时存活但指针不存在?
这里的答案存在一个问题,即似乎存在两种截然相反且相互矛盾的解决方案,并且没有就真理达成共识。我希望能够在删除shared_ptr后使用引用,但如果它无效,我真的需要理解这一点。
也许有人可以发布一个简单的例子来演示引用中未定义的行为。
答案 0 :(得分:12)
因为r = *sp;
没有按照您的想法行事。它将引用分配给您在第1行中在堆上创建的匿名int
对象。您无法在C ++中重新引用引用。
以下是标准关于评估参考表达式的内容:
如果表达式最初具有“
T
的引用”类型, 在进行任何进一步分析之前,将类型调整为T
。 表达式指定由引用表示的对象或函数, 表达式是左值或x值,具体取决于表达式。
所以你看,没有办法得到“引用本身”。它在C ++中根本就不存在。
也许这段代码会更清晰:
int a = 42;
int b = 97;
int&r = a; // r is just an alias (another name) for a
r = b; // assigns b to a (does NOT bind r to b, that's impossible in C++!)
执行最后一行后,a
和b
都包含97,因为r = b
实际上意味着a = b
。
答案 1 :(得分:2)
p未定义,r是副本
int& r = *(new int(0));
{
boost::shared_ptr<int> sp(new int(100));
r = *sp; // copy
cout << "r=" << r << endl;
}
cout << "r=" << r << endl << endl;
int* p;
{
boost::shared_ptr<int> sp(new int(100));
p = &*sp;
cout << "*p=" << *p << endl;
}
cout << "*p=" << *p << endl; // Undefined, pointer points to deleted int
答案 2 :(得分:0)
在第二种情况下,您的int
- 对象被破坏。在第一种情况下,它不是。
在第一种情况下,您在外部作用域中创建一个int
- 对象new
。在内部范围中,您创建第二个int
- 对象,您还可以为其创建shared_ptr
,然后拥有int
- 对象。关闭内部范围时,此shared_ptr
超出范围,因此会被破坏。 shared_ptr
析构函数也会破坏它引用的对象,因为没有其他shared_ptr
(从原始对象创建)再次引用您的int
对象。这一切都没问题。但是,在该范围的中间,您将r
的值重新指定为*sp
(100)的值。因此,在*sp
被破坏之前,sp
的价值会保存到r
。
注意:在第一行代码中创建int
对象的方式肯定有问题。如果您没有显式删除该int
对象,那么这就是内存韭菜。破坏它的方法是delete &r
,它看起来非常难看,特别是因为之后的符号r
仍然引用了现在已删除的int
对象。不要这样做!
在第二种情况下,您在开头创建了一个int
指针,但没有int
个对象。内部范围几乎与以前相同,除了这次你没有将新int
对象的值保存到外部范围变量(p
)中,但是你保存了地址范围。 int
对象!当int
对象在内部范围的末尾被破坏时(出于与先前相同的原因),p
不再指向现有的int
对象,而是指向内存中的某个位置以前曾经拥有一个int
对象。您从*p
获得的值未定义:您可能仍然获得100,您可以获得任何其他值,甚至可能会崩溃您的程序(分段错误),因为您取消引用不再存在的内存位置。 / p>
总结一下,并回答你的最后一个问题:
引用仍然存在,因为它仍然引用现有对象。指针不会,因为它指向不再存在的对象。