绑定const和临时:没有编译器警告?

use*_*187 11 c++ const-reference

我有TestClass一个const&成员变量.我从各个地方和自己的经验中知道const&,通过引用临时值来初始化它是一个坏主意.所以我很惊讶的是,下面的代码将编译罚款(经测试gcc-4.9.1,clang-3.5scan-build-3.5),但不能正常运行.

class TestClass {
  public:
    // removing the "reference" would remove the temporary-problem
    const std::string &d;

    TestClass(const std::string &d)
        : d(d) {
        // "d" is a const-ref, cannot be changed at all... if it is assigned some
        // temporary value it is mangled up...
    }
};

int main() {

    // NOTE: the variable "d" is a
    // temporary, whose reference is not valid... what I don't get in the
    // moment: why does no compiler warn me?
    TestClass dut("d");

    // and printing what we got:
    std::cout << "beginning output:\n\n";
    // this will silently abort the program (gcc-4.9.1) or be empty
    // (clang-3.5) -- don't know whats going on here...
    std::cout << "dut.d: '" << dut.d << "'\n";
    std::cout << "\nthats it!\n";

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

为什么两个编译器都没有在编译时警告我?另见这个想法,还有一些测试正在进行中.

Ale*_*dan 9

没有警告没有冒犯:

本地const引用可延长变量的生命周期.

该标准在§8.5.3/ 5 [dcl.init.ref]中指定了这种行为,这是关于参考声明的初始化者的部分.生命周期扩展不是通过函数参数传递的.§12.2/ 5 [class.temporary]:

第二个上下文是引用绑定到临时的.除了下面指定的内容之外,引用绑定的临时对象或作为临时绑定对象的子对象的完整对象的临时对象的生命周期仍然存在.绑定到构造函数的ctor-initializer(第12.6.2节[class.base.init])中的引用成员的临时绑定将持续存在,直到构造函数退出.在函数调用(第5.2.2节[expr.call])中对引用参数的临时绑定将持续存在,直到包含该调用的完整表达式完成为止.

您可以查看一下getw-88,以便对此主题进行扩展且更具可读性的讨论.

未定义的行为

那你的代码是否正确?不,它的执行将导致未定义的行为.代码快照中的真正问题是,未定义的行为是由两个完全合法的操作混合引起的:构造函数的调用传递临时对象(其生命跨越构造函数块)以及构造函数中引用的绑定定义.

编译器不够智能,无法检测到这种爆炸性的语句组合,所以这就是你没有得到任何警告的原因.

  • @j_random_hacker为什么不是错误?好问题:我想不出你为什么要这样做的任何理由.但是正交性以及你应该给程序员所需要的所有绳索的原则可能就是它在脚下的基础. (2认同)