C++ 临时奇数的常量引用

C++ 临时奇数的常量引用,c++,reference,constants,temporary,C++,Reference,Constants,Temporary,我们都知道这样的东西在c++中是有效的: const T &x = T(); 而: T &x = T(); 事实并非如此 在对话中,引导我们遵循这条规则。OP发布了一些代码,这些代码清楚地唤起了UB。但我希望它的修改版本能够工作(这是修改版本): 每次打印10。至少似乎常量引用规则对int版本有效,但对类版本无效。它们都是由于堆的使用而导致的吗?我很幸运使用了int版本,因为编译看穿了所有consts并直接打印出了10?我缺少规则的哪一方面?它简单地说明了通过“在编译器中尝试

我们都知道这样的东西在c++中是有效的:

const T &x = T();
而:

T &x = T();
事实并非如此

在对话中,引导我们遵循这条规则。OP发布了一些代码,这些代码清楚地唤起了UB。但我希望它的修改版本能够工作(这是修改版本):


每次打印
10
。至少似乎常量引用规则对
int
版本有效,但对类版本无效。它们都是由于堆的使用而导致的吗?我很幸运使用了
int
版本,因为编译看穿了所有
const
s并直接打印出了
10
?我缺少规则的哪一方面?

它简单地说明了通过“在编译器中尝试”来分析语言行为通常不会产生任何有用的结果。由于同样的原因,你的两个例子都是无效的

只有当您将临时变量用作常量引用的直接初始值设定项时,临时变量的生存期才会延长—只有这样才能在引用和临时变量之间建立“生存期”链接

尝试将临时变量作为构造函数的参数传递并在构造函数内附加const引用不会建立上述链接,也不会延长临时变量的生存期

也可以按照C++标准,如果你这样做< /P>

struct S {
  const int &r;

  S() : r(5) {
    cout << r; // OK
  }
};
结构{
康斯特国际研究中心;
S():r(5){

你真走运。将B::B更改为:

void b() {
    int i = rand();
    int j = rand();
    cout << _a << endl;
}
void b(){
int i=rand();
int j=rand();
库特
每次打印10张

稍微修改主功能,它将不再打印10:

int main()
{
    B* p = f();
    cout << "C++\n";   // prints C++
    p->b();            // prints 4077568
}
intmain()
{
B*p=f();
cout b();//打印4077568
}
如何在什么级别建立此链接

见第12.2节[临时类]§4和§5:

临时对象将被销毁,这是计算完整表达式的最后一步,该表达式(在词汇上)包含创建临时对象的点

有两种情况下,时间单位在完全表达结束时的不同点被销毁。 第一个上下文是[…]

第二个上下文是引用绑定到临时对象时。该引用绑定到的临时对象或作为该引用绑定到的子对象的完整对象的临时对象在引用的生存期内持续存在,除了:[……]

函数调用中与引用参数的临时绑定将持续存在,直到包含该调用的完整表达式完成


因此,在您的情况下,在计算完完整表达式后,临时表达式将被销毁。
new B(A(10))

我建议您将“一个常量引用”更改为“一个本地常量引用”,以使事情更清楚;)@fredwolflow:您为什么坚持使用本地引用?您可以合法地声明
const std::string&r=“Hello”
在命名空间范围内,并获得相同的生存期扩展。@AndreyT,这个链接是如何在什么级别建立的?哦,我忘记了全局变量。我想“非成员常量引用”是我真正的意思:)它很可能起作用,因为编译器优化了引用,使其不存在,而只是复制了整数。
S s;
cout << s.r; // Invalid
void b() {
    int i = rand();
    int j = rand();
    cout << _a << endl;
}
int main()
{
    B* p = f();
    cout << "C++\n";   // prints C++
    p->b();            // prints 4077568
}