gpt4 book ai didi

c++ - 为什么临时获取右值的地址是非法的?

转载 作者:IT老高 更新时间:2023-10-28 12:58:45 25 4
gpt4 key购买 nike

根据“How to get around the warning "rvalue used as lvalue"?”,Visual Studio 只会对如下代码发出警告:

int bar() {
return 3;
}

void foo(int* ptr) {

}

int main() {
foo(&bar());
}

在 C++ 中,不允许获取临时地址(或者,至少是由 rvalue 表达式引用的对象的地址?),而我认为这是因为临时对象甚至不能保证有存储空间。

但是,尽管诊断可以以编译器选择的任何形式呈现,我仍然希望 MSVS 在这种情况下 error 而不是 warn

那么,临时存储是否保证有存储空间?如果是这样,为什么上面的代码首先被禁止?

最佳答案

实际上,在原始语言设计中, 允许使用临时地址。正如您正确注意到的那样,没有技术上的理由不允许这样做,并且 MSVC 今天仍然通过非标准语言扩展允许它。

C++ 将其设为非法的原因是对临时对象的绑定(bind)引用与从 C 继承的另一个 C++ 语言特性发生冲突:隐式类型转换。考虑:

void CalculateStuff(long& out_param) {
long result;
// [...] complicated calculations
out_param = result;
}

int stuff;
CalculateStuff(stuff); //< this won't compile in ISO C++

CalculateStuff() 应该通过输出参数返回其结果。但真正发生的是:该函数接受一个long&,但得到一个int 类型的参数。通过 C 的隐式类型转换,int 现在隐式转换为 long 类型的变量,在此过程中创建了一个未命名的临时。因此,该函数实际上不是在变量 stuff 上运行,而是在一个未命名的临时对象上运行,并且一旦该临时对象被销毁,该函数应用的所有副作用都将丢失。 stuff 变量的值永远不会改变。

在 C++ 中引入了引用以允许运算符重载,因为从调用者的角度来看,它们在语法上与按值调用相同(与指针调用相反,指针调用需要显式的 & on调用方)。不幸的是,当与 C 的隐式类型转换结合使用时,正是这种语法等价导致了麻烦。

由于 Stroustrup 想要保留这两个特性(引用和 C 兼容性),他引入了我们今天都知道的规则:未命名的临时对象只绑定(bind)到 const 引用。使用该附加规则,上述示例不再编译。由于该问题仅在函数将副作用应用于引用参数时发生,因此将未命名的临时对象绑定(bind)到 const 引用仍然是安全的,因此仍然允许这样做。

整个故事也在 C++ 的设计和演变的第 3.7 章中进行了描述:

The reason to allow references to be initialized by non-lvalues was to allow the distinction between call-by-value and call-by-reference to be a detail specified by the called function and of no interest to the caller. For const references, this is possible; for non-const references it is not. For Release 2.0 the definition of C++ was changed to reflect this.

我还依稀记得曾在一篇论文中第一次发现这种行为,但我现在不记得了。也许有人可以帮助我?

关于c++ - 为什么临时获取右值的地址是非法的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8763398/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com