为什么这样做?在C ++中返回const引用

时间:2010-02-07 18:34:29

标签: c++ const const-reference

我正在使用C ++和const引用,并且很困惑为什么这段代码有效:

#include <iostream>

class A {
public:
    A() : a_(50) {}
    const int& getA() const { return a_; }
private:
    const int a_;
};

int main(int argc, char* argv[])
{
    A* a = new A();
    const int& var = a->getA();
    std::cout << var << std::endl;
    delete a;
    std::cout << var << std::endl;
}

结果:

50
50

以下是我的想法:

var存储对a_的引用 删除a时,也应删除a_ 当再次访问var时,它不再包含有效的引用,并且应该发生分段错误。

为什么这样做?我不相信我是临时副本。

4 个答案:

答案 0 :(得分:13)

您删除a的那一刻,访问var成为您进入未定义行为的大门。

偶然“工作”。 var所指的空间不再是你的空间,但这一次你已经逃脱了访问它。它可能导致分段错误,返回50以外的数字,或重新格式化您的硬盘。

请记住,似乎工作是未定义行为可以表现出来的一种可能方式。

答案 1 :(得分:3)

删除对象不会清除内存。在内存用于其他内容之前,该值仍将存在。所以它可能会工作一段时间......

某些C ++实现具有“调试模式”,可以为所有已删除的内存设置特定值,以检测此类错误。

答案 2 :(得分:2)

当您删除a时,您正在释放内存并允许后一个新内存覆盖它。在此之前,已删除对象中的所有变量仍在内存中,但可以随时覆盖。

答案 3 :(得分:1)

由于const关键字,这非常棘手。

是的,在这种情况下你可能正在阅读未初始化的内存。对此的一些想法:

  1. 你没有使用调试模式:只要代码没有经过测试,这通常不是一个好主意,但它有两个选择:
    • 发布模式内存管理器不会覆盖内存,因此您可以访问最后一个已知地址,该地址仍然有效
    • OR整个操作已完全优化,因为编译器知道您没有更改该值并且无法从外部更改(尽管由于C ++中const正确性的限制,这可能不正确)
  2. 您处于调试模式,但已激活优化,因此应用相同的参数
  3. _a的内容,因为标记为const不是堆分配的,也不是堆栈分配但位于应用程序的DATA部分,所以引用可能确实是仍然有效,不仅仅是偶然。 [编辑]:这只适用于static const变量。
  4. 您可能会考虑编写自定义内存管理器或研究编译器的调试模式行为,因为这非常非常重要。例如,Visual Studio会将变量设置为0xCDCDCDCD。您还可以在数组末尾找到有趣的值,例如0xDEADC0DE