右值引用被视为左值?
Rvalue Reference is Treated as an Lvalue?
我发布了这个答案: 其中包含以下代码:
void foo(string&& bar){
string* temp = &bar;
cout << *temp << " @:" << temp << endl;
}
bar
是右值还是左值?
我问是因为我显然不能获取右值的地址,但我可以像这里所做的那样获取右值引用的地址。
如果您可以对右值引用执行您可以对左值引用执行的任何操作,那么使用“&&”而不是仅仅使用“&”来区分两者有什么意义?
Is bar
an rvalue or an lvalue?
问题自己回答。任何有名字的东西都是左值(1)。所以 bar
是一个左值。它的类型是"rvalue reference to string
",但它是该类型的左值。
如果要将其视为右值,则需要对其应用 std::move()
。
If you can perform any operation on an rvalue reference that you can on an lvalue reference what is the point in differentiating between the two with the "&&" instead of just an "&"?
这取决于您对 "perform an operation." 的定义 "perform an operation." 左值引用和(命名的)右值引用在您如何在表达式中使用它们方面几乎相同,但它们有很大的不同在什么地方可以绑定到他们。左值可以绑定到左值引用,右值可以绑定到右值引用(任何东西都可以绑定到 const
的左值引用)。也就是说,您不能将右值绑定到左值引用,反之亦然。
再说一个右值引用类型的函数参数(比如你的bar
)。重要的一点不是 bar
是什么,而是您对 bar
所指的值了解多少。由于 bar
是一个右值引用,您可以肯定地知道绑定到它的 是一个右值。 这意味着它一定会在完整表达式结束时被销毁,您可以安全地将其视为右值(通过窃取其资源等)。
如果您不是直接向 bar
执行此操作的人,而只是想将 bar
传递给其他人,则您有两个选择:要么完成 bar
, 然后你应该告诉下一个收到它的人它绑定到一个右值——做 std::move(bar)
。或者你需要用 bar
做一些更多的事情,所以你不希望中间的任何人从你下面窃取它的资源,所以把它当作一个左值——bar
.
总结一下:不同之处不在于你可以用参考文献做什么。不同之处在于可以绑定到 引用。
(1) 一个很好的经验法则,除了一些小的例外:枚举数有名字,但是是右值。 类、命名空间和 class 模板有名称,但没有值。
Is bar an rvalue or an lvalue?
这是一个左值,任何命名变量的表达式也是如此。
If you can perform any operation on an rvalue reference that you can on an lvalue reference what is the point in differentiating between the two with the "&&" instead of just an "&"?
您只能使用 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
在这种情况下,命名的右值引用是左值,而如果输入类型是const named rvalue references 那么它将是rvalue,这里是一个简单的例子:
#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;
}
希望这有用。
表达式bar
是一个左值。但它不是 "rvalue reference to string"。表达式 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
If you can perform any operation on an rvalue reference that you can on an lvalue reference what is the point in differentiating between the two with the "&&" instead of just an "&"?
右值引用允许我们在右值过期之前做一些"lvalue operations"。
我发布了这个答案:
void foo(string&& bar){
string* temp = &bar;
cout << *temp << " @:" << temp << endl;
}
bar
是右值还是左值?
我问是因为我显然不能获取右值的地址,但我可以像这里所做的那样获取右值引用的地址。
如果您可以对右值引用执行您可以对左值引用执行的任何操作,那么使用“&&”而不是仅仅使用“&”来区分两者有什么意义?
Is
bar
an rvalue or an lvalue?
问题自己回答。任何有名字的东西都是左值(1)。所以 bar
是一个左值。它的类型是"rvalue reference to string
",但它是该类型的左值。
如果要将其视为右值,则需要对其应用 std::move()
。
If you can perform any operation on an rvalue reference that you can on an lvalue reference what is the point in differentiating between the two with the "&&" instead of just an "&"?
这取决于您对 "perform an operation." 的定义 "perform an operation." 左值引用和(命名的)右值引用在您如何在表达式中使用它们方面几乎相同,但它们有很大的不同在什么地方可以绑定到他们。左值可以绑定到左值引用,右值可以绑定到右值引用(任何东西都可以绑定到 const
的左值引用)。也就是说,您不能将右值绑定到左值引用,反之亦然。
再说一个右值引用类型的函数参数(比如你的bar
)。重要的一点不是 bar
是什么,而是您对 bar
所指的值了解多少。由于 bar
是一个右值引用,您可以肯定地知道绑定到它的 是一个右值。 这意味着它一定会在完整表达式结束时被销毁,您可以安全地将其视为右值(通过窃取其资源等)。
如果您不是直接向 bar
执行此操作的人,而只是想将 bar
传递给其他人,则您有两个选择:要么完成 bar
, 然后你应该告诉下一个收到它的人它绑定到一个右值——做 std::move(bar)
。或者你需要用 bar
做一些更多的事情,所以你不希望中间的任何人从你下面窃取它的资源,所以把它当作一个左值——bar
.
总结一下:不同之处不在于你可以用参考文献做什么。不同之处在于可以绑定到 引用。
(1) 一个很好的经验法则,除了一些小的例外:枚举数有名字,但是是右值。 类、命名空间和 class 模板有名称,但没有值。
Is bar an rvalue or an lvalue?
这是一个左值,任何命名变量的表达式也是如此。
If you can perform any operation on an rvalue reference that you can on an lvalue reference what is the point in differentiating between the two with the "&&" instead of just an "&"?
您只能使用 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
在这种情况下,命名的右值引用是左值,而如果输入类型是const named rvalue references 那么它将是rvalue,这里是一个简单的例子:
#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;
}
希望这有用。
表达式bar
是一个左值。但它不是 "rvalue reference to string"。表达式 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
If you can perform any operation on an rvalue reference that you can on an lvalue reference what is the point in differentiating between the two with the "&&" instead of just an "&"?
右值引用允许我们在右值过期之前做一些"lvalue operations"。