C ++构造函数:初始化const引用时的垃圾

时间:2012-02-04 06:45:18

标签: c++ constructor reference const

这段代码出了什么问题,为什么我得错了答案:

class X
{
private:
        const int a;
        const int& b;
public:
        X(): a(10) , b(20)
        {
        //      std::cout << "constructor : a " << a << std::endl;
        //      std::cout << "constructor : b " << b << std::endl;
        }

        void display()
        {
            std::cout << "display():a:" << a << std::endl;
            std::cout << "display():b:" << b << std::endl;

        }
};


int
main(void)
{
        X x;
        x.display();
return 0;
}

上面的代码会给我结果

display():a:10
display():b:1104441332

但是如果我删除默认构造函数中的注释2行,它会给我正确的结果

constructor : a 10
constructor : b 20
display():a:10
display():b:20

请帮助,谢谢

4 个答案:

答案 0 :(得分:24)

您正在初始化b作为对临时的引用。

创建值20,仅存在于构造函数的范围内。

此后代码的行为非常有趣 - 在我的机器上,我从你发布的那些中得到不同的值,但基本行为仍然是不确定的。

这是因为当引用点超出范围的值时,它开始引用垃圾内存,从而产生不可预测的行为。

Does a const reference prolong the life of a temporary?;答案https://stackoverflow.com/a/2784304/383402链接到C ++标准的相关部分,特别是以下文本:

A temporary bound to a reference member in a constructor’s ctor-initializer
(12.6.2) persists until the constructor exits.

这就是为什么你总是在构造函数中的print中获得正确的值,并且很少(但有时可能!)之后。当构造函数退出时,引用悬​​空并且所有下注均已关闭。

答案 1 :(得分:19)

我会让我的编译器回答这个问题:

$ g++ -std=c++98 -Wall -Wextra -pedantic test.cpp
test.cpp: In constructor 'X::X()':
test.cpp:9:26: warning: a temporary bound to 'X::b' only persists until the constructor exits [-Wextra]
$

您也应该打开编译器上的警告。

答案 2 :(得分:4)

b是指临时的。您读取的内容(打印时)在读取时是无效的位置,因为临时20在技术上超出了范围。

解释不一致的结果:

这是未定义的行为。如果您:

,您所看到的可能会有所不同
  • 更改编译器
  • 更改编译器设置
  • 构建另一个架构
  • 更改班级的“会员布局”
  • x
  • 实例附近的内存区域中添加或删除内容

您应始终始终避免未定义的行为。

但为什么值会改变?您的引用可能是指在打印时已重写(例如重复使用)的堆栈地址。

答案 3 :(得分:3)

您将const&绑定到一个临时的,它不会超出对构造函数的调用。 C ++ 03标准明确指出&#34;构造函数的ctor-initializer(12.6.2)中对引用成员的临时绑定一直存在,直到构造函数退出&#34; (12.2 / 5&#34;临时物品&#34;)。

因此,您的代码具有未定义的行为 - 您可能会听到废话,或者似乎正在工作的内容。

FWIW,MSVC 2010对该代码发出以下警告:

C:\temp\test.cpp(12) : warning C4413: 'X::b' : reference member is initialized to a temporary that doesn't persist after the constructor exits