c++ 当在函数中使用右值引用时,是否将其视为左值?

ghhkc1vu  于 12个月前  发布在  其他
关注(0)|答案(4)|浏览(66)

我发布了这个答案:https://stackoverflow.com/a/28459180/2642059其中包含以下代码:

void foo(string&& bar){
    string* temp = &bar;

    cout << *temp << " @:" << temp << endl;
}

字符串
bar是左值还是右值?
我之所以问这个问题,是因为我显然不能取右值的地址,但我可以像这里一样取右值引用的地址。
如果你可以在右值引用上执行任何你可以在左值引用上执行的操作,那么用“&&”而不仅仅是“&"来区分两者有什么意义呢?

kyks70gy

kyks70gy1#

bar是左值还是右值?
这个问题本身就有答案了。任何有名字的东西都是一个左值(1)。所以bar是一个左值。它的 type 是“对string的右值引用“,但它是那种类型的左值。
如果要将其视为右值,则需要对它应用std::move()
如果你可以在右值引用上执行任何你可以在左值引用上执行的操作,那么用“&&”而不仅仅是“&"来区分两者有什么意义呢?
这取决于你对“执行操作”的定义。左值引用和(命名的)右值引用在你如何在表达式中使用它们方面几乎是一样的,但是它们在绑定到它们的对象方面有很大的不同。左值可以绑定到左值引用,右值可以绑定到右值引用(任何东西都可以绑定到const的左值引用),也就是说,你不能将右值绑定到左值引用,反之亦然。
让我们来讨论一个右值引用类型的函数参数(例如bar)。重点不是bar是什么,而是您对bar引用的值了解多少。由于bar是一个右值引用,因此您可以确定绑定到它的任何内容 * 都是一个右值。* 这意味着当完整表达式结束时,它必然会被销毁。您可以安全地将其视为右值(通过窃取其资源等)。
如果您不是直接向bar执行此操作的人,而只是想将bar传递给它,则有两种选择:要么你已经处理完了bar,然后你应该告诉下一个接收它的人它绑定到了一个右值-do std::move(bar),要么你需要对bar做更多的事情,所以你不想让任何人从你下面窃取它的资源,所以就把它当作一个左值-bar
总结一下:区别不在于拥有引用 * 后您可以对其执行哪些操作。 区别在于可以将哪些内容 * 绑定到 * 引用。*
(1)这是一个很好的经验法则,但有一些小的例外:枚举数有名称,但是右值;类、命名空间和类模板有名称,但不是值。

yv5phkfx

yv5phkfx2#

bar是右值还是左值?
它是一个左值,就像任何命名变量的表达式一样。
如果你可以在一个 * 右值 * 引用上执行任何操作,你可以在一个 * 左值 * 引用上执行任何操作,那么用“&&”而不仅仅是“&”来区分两者有什么意义呢?
你只能用一个 * rvalue* 表达式初始化一个 * rvalue* 引用。所以你可以传递一个临时字符串给你的函数,但是你不能传递一个字符串变量而不显式地从它移动。这意味着你的函数可以假设参数不再需要,并且可以从它移动。

std::string variable;
foo(variable);            // ERROR, can't pass an lvalue
foo(std::move(variable)); // OK, can explicitly move
foo("Hello");             // OK, can move from a temporary

字符串

gz5pxeao

gz5pxeao3#

表达式bar是一个左值。但它不是“对字符串的右值引用”。表达式bar是一个左值引用。你可以通过在foo()中添加以下行来验证它:

cout << is_lvalue_reference<decltype((bar))>::value << endl; // prints "1"

字符串
但我同意Angew的其他解释。
一个右值引用,在它被绑定到一个右值之后,是一个左值引用。实际上它不仅仅是函数参数:

string&& a = "some string";
string&& b = a; // ERROR: it does not compile because a is not an rvalue


如果你可以在右值引用上执行任何你可以在左值引用上执行的操作,那么用“&&”而不仅仅是“&"来区分两者有什么意义呢?
右值引用允许我们在右值过期之前做一些“左值操作”。

gt0wga4j

gt0wga4j4#

在这种情况下,* 命名右值引用是左值 *,而如果输入类型是 const命名右值引用 ,则它将是 * 右值

#include <string>
#include <iostream>

void foo(const std::string&& bar) { 
    std::string* temp = &bar; // compile error, can't get address
    std::cout << *temp << " @:" << temp << std::endl;
}

int main()
{
    foo("test");
    return 0;
}

字符串

相关问题