如何解决为什么右值引用参数不能直接在函数之间传递?
我的代码如下:
#include <iostream>
using namespace std;
class A{
public:
void sendByRvalue(string&& str){
cout << str << endl;
}
};
class B{
private:
A a;
void send(string&& str){
a.sendByRvalue(str);
}
public:
void run(const string& str){
send("run " + str + "\n");
}
};
int main(void){
string str("hello world");
B b;
b.run(str);
return 0;
}
似乎str
中的B::send
已更改为lvalue。然后,我更改B::send
的实现,例如:
class B{
private:
A a;
void send(string&& str){
cout << boolalpha << is_rvalue_reference<decltype(str)>::value << endl;
a.sendByRvalue(std::move(str));
}
public:
void run(const string& str){
send("run " + str + "\n");
}
};
为什么参数str是右值引用,但是没有A::sendByRvalue
我不能将其直接传递给函数std::move
吗?
解决方法
str
是一个命名的右值引用,该引用在语言中被视为左值。 rvalue只是xvalue或prvalue,str
都不是。
来自the standard的关于xvalue规则的注释:
通常,此规则的作用是将已命名的右值引用视为左值,将对对象的未命名的右值引用视为左值;不论是否命名,对函数的右值引用均视为左值。
struct A {
int m;
};
A&& operator+(A,A);
A&& f();
A a;
A&& ar = static_cast<A&&>(a);
,表达式
f()
,f().m
,static_cast<A&&>(a)
和a + a
是x值。表达式ar
是一个左值。
我将做一个简单的例子来解释
void bar(std::string&& name) {
std::cout << "Bar: " << name << std::endl;
}
void foo(std::string&& name) {
bar(name);
}
int main() {
foo("C++");
}
这与您提供的示例大致相同。在foo()
中, name
是左值。临时字符串C++
是 rvalue ,它被传递到name
中。 name
是左值。因此,上面的代码基本上被翻译成。
void bar(std::string&& name) {
std::cout << "Bar: " << name << std::endl;
}
int main()
{
std::string foo{ "C++" };
bar(foo);
}
现在看来问题出在哪里。
我写了这个简单的程序来帮助您更好地理解
void foo(const std::string& name) {
std::cout << "Passed as lvalue ref: " << name << std::endl;
}
void foo(std::string&& name) {
std::cout << "Passed as rvalue ref: " << name << std::endl;
}
我们将使用此函数调用
void bar(std::string&& name) {
foo(name);
}
int main() {
bar("C++");
}
作为左值引用传递:C ++
这证明了我的观点,现在如果我们使用std::move()
会怎样?
void bar(std::string&& name) {
foo(std::move(name));
}
int main() {
bar("C++");
}
作为右值引用传递:C ++
如果您想要一种简单的方法来检查表达式是左值还是右值,则可以尝试以下代码段
template <typename T>
constexpr bool is_lvalue(T&) {
return true;
}
template <typename T>
constexpr bool is_lvalue(T&&) {
return false;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。