【问题标题】:Why does this work? Returning const references in C++为什么这行得通?在 C++ 中返回 const 引用
【发布时间】:2010-02-07 18:34:29
【问题描述】:

我在玩弄 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 时,它不再包含有效的引用,应该会发生分段错误。

为什么会这样?我不相信我会制作临时副本。

【问题讨论】:

    标签: c++ constants const-reference


    【解决方案1】:

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

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

    请记住,看起来有效是未定义行为表现出来的一种可能方式。

    【讨论】:

    • 这是我最好的猜测——它在这种情况下有效,但它具有未定义的行为。绝对不能保证有效,而且非常危险。
    • 更糟糕的是 - 在调试/发布和单/双核 CPU 上表现不同的错误之一
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      当您删除 a 时,您将释放内存并允许后者 new 覆盖它。在此之前,已删除对象中的所有变量仍在内存中,但可能随时被覆盖。

      【讨论】:

        【解决方案4】:

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

        没错,在这种情况下,您可能正在读取未初始化的内存。对此的一些想法:

        1. 您没有使用调试模式:只要代码尚未经过测试,这通常不是一个好主意,但它留下了两个选项:
          • 释放模式内存管理器不会覆盖内存,因此您访问最后一个已知地址,这仍然是偶然的
          • 或者整个操作被完全优化掉,因为编译器知道你没有改变值并且它不能从外部改变(尽管由于 C++ 中 const 正确性的限制,这可能不是真的)李>
        2. 您处于调试模式,但已激活优化,因此适用相同的参数
        3. _a 的内容,因为标记为const 不是堆分配的,也不是堆栈分配的,而是驻留在应用程序的DATA 部分,所以引用可能确实仍然有效,这不仅仅是偶然的。 [编辑]:这仅适用于 static const 变量。

        您可能会考虑编写自定义内存管理器或研究编译器的调试模式行为,因为这非常非常重要。例如,Visual Studio 会将变量设置为 0xCDCDCDCD。您还会在数组末尾找到有趣的值,例如 0xDEADC0DE

        【讨论】:

        • 关于 (3),_a 可能位于“DATA 部分”中的唯一方法是编译器执行广泛的静态分析并确定只有 1 个 A 实例,在这种情况下,整个对象都会在那里。 const 成员仍然占用对象的每个实例中的空间。
        • 非常正确...相应地编辑了我的答案。感谢您纠正我。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-04
        • 2017-10-31
        • 2020-07-17
        相关资源
        最近更新 更多