我不明白下面的代码是如何编译/不编译的:
struct Temp
{
int i;
};
int main(int argc, char * argv[])
{
//Temp &ref1 = (Temp){42}; // Error, as expected
Temp &ref2 = *(Temp*)&(Temp){42}; // A-OK
std::cerr << ref2.i << std::endl;
return 0;
}
我正在使用 g++ 4.4.4。
最佳答案
您的代码不是真正的 C++。它使用复合文字,这是 C99 的一个特性。在 C99 中,它计算为一个左值,并且获取文字的地址在那里完全没问题。将此扩展集成到 C++ 中,GCC 似乎改变了它的规则并使其成为右值,从而更好地将它们的分类纳入 C++ 的现有规则中,以用于也产生右值的常规转换。
GCC 不喜欢 &(Temp){42}
,提示我拿了临时地址。这是一个关于无效代码的警告,它仍然接受但并不真正喜欢。对于其他明显错误的代码,如 &A()
也会给出相同的警告,这是一种合法的函数式 C++ 转换,它也会产生一个右值,因此不能用作地址的操作数运算符(operator)。
GCC 将复合文字集成到 C++ 中也过早地破坏了临时变量,如下面的测试可以看出
#include <iostream>
struct B {
~B() {
std::cout << "~B" << std::endl;
}
};
struct A { int i; B b; };
int main() {
A *a = &(A){0};
std::cout << "main" << std::endl;
}
在 C99 中,字面量所指的对象在整个 block 中都是有效的(它将具有自动存储持续时间)。在 GNU C++ 中,对象已经在完整表达式的末尾被破坏,甚至在到达其 block 末尾之前(“~B”打印在“main”之前)。
关于c++ - 通过指针转换将右值绑定(bind)到非常量引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5061275/