boost :: shared_ptr问题。为什么这样做?

时间:2010-12-08 16:59:43

标签: c++ pointers reference shared-ptr

在试验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后使用引用,但如果它无效,我真的需要理解这一点。

也许有人可以发布一个简单的例子来演示引用中未定义的行为。

3 个答案:

答案 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++!)

执行最后一行后,ab都包含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>

总结一下,并回答你的最后一个问题:

引用仍然存在,因为它仍然引用现有对象。指针不会,因为它指向不再存在的对象。