gpt4 book ai didi

c++ - r-value ref 到 l-value ref 的转换,为什么有效?

转载 作者:行者123 更新时间:2023-11-30 01:56:46 25 4
gpt4 key购买 nike

在我看来,将右值引用转换为左值引用并赋予最终访问临时值作为左值的能力是没有意义的。例如:

struct S
{
int val=5;
};

void foo(S &&s)
{
S &s2=s;

s2.val=7
}

void foo2(S &s2)
{
s2.val=7
}

int main()
{
foo(S()); // This is fine
foo2(S()); // Error: Even though this is logically equivalent to foo()
}

foo() 的调用在 C++ 中似乎是有效的,或者至少它是用 gcc 4.7.1 编译的。对 foo2() 的调用不是,即使这两个函数在逻辑上看起来是等价的。给了什么?

最佳答案

s 已经是一个左值,就像任何其他命名变量一样。所以对它有一个左值引用并没有真正改变任何东西。

右值和左值在概念上的主要区别是您只能访问一个右值一次,这使得对它做奇怪的事情是安全的。但是如果那个访问将它绑定(bind)到一个右值引用,你就创建了一种多次访问它的方法,即将它变成一个左值。所以您不能将它隐式绑定(bind)到另一个右值引用,而您可以将它绑定(bind)到一个左值引用。

编辑:

这两件事在逻辑上是等价的。一种是将右值绑定(bind)到左值引用。这是不允许的,因为它具有误导性。 (不像允许左值绑定(bind)到右值引用那么危险,但仍然具有误导性。)foo2,通过采用左值引用,宣布它可能会修改传递的对象,这绝对是功能操作的核心部分。将临时值传递给这样的函数没有意义,因为您无法观察到修改。

在另一种情况下,您将右值绑定(bind)到右值引用。 foo,通过采用右值引用,宣布它可能会修改传递的对象,但这是一种性能优化,并不意味着任何外部人员都可以观察到。传递一个临时值是有道理的,但传递一个非临时值将是非常危险的,这就是为什么在这种情况下您必须显式地std::move 参数。

然后,在 foo 中,您将左值(恰好是一个引用右值引用类型变量的表达式,但这无关紧要)绑定(bind)到一个左值表达式。这是有道理的:你有你的右值引用变量 s ,它指向一些东西,由于已经传递给你的函数,它已经成为你的玩物。因此,如果您想将其传递给修改其状态的对象(例如 foo2),然后观察更改(您可以通过 ss2 两者),这在概念上是完美的。

基本上,只能观察一次或多次是范围问题。这就是为什么“相同”的东西(这不是真正的东西,但你是这样想的)可以在一个上下文中绑定(bind)到右值引用,而在另一个上下文中绑定(bind)到左值引用。

关于c++ - r-value ref 到 l-value ref 的转换,为什么有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19521664/

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