【发布时间】:2021-11-30 19:58:37
【问题描述】:
我试图更好地理解 LValue、RValue 以及 std::move 的工作原理。 我有以下代码
#include <string>
class A
{
public:
A() = default;
A(std::string&& aString): myString(std::move(aString)) {}
std::string myString;
};
class B
{
public:
void InitMembers(std::string& aString) { myA = A(std::move(aString));}
private:
A myA;
};
int main()
{
B b;
std::string hello;
b.InitMembers(hello);
}
我的问题是:
- 在
void InitMembers(string& aString) { myA = A(std::move(aString));}中,我知道我必须使用std::move 到aString 才能将aString 从LValue 引用转换为RValue 引用。但是我对 InitMember 范围内的 aString 的含义有些怀疑。 aString 作为 LValue 引用提供,但在方法范围内它被视为 LValue,这就是为什么我必须使用 std::move? Std::move 应该依赖于引用推导(对吗?),在这种情况下它如何推导类型?它会推导出一个类型 "string" o "string&",因为 aString 在方法的参数中作为 LValue 引用提供? - 为什么我还必须在 A 的构造函数初始化程序中使用 std::move? aString 是触发移动构造函数的 RValue 引用这一事实还不够吗?
下面的实现是不是和上面的一样好?
#include <string>
class A
{
public:
A() = default;
A(std::string& aString): myString(std::move(aString)) {}
std::string myString;
};
class B
{
public:
void InitMembers(std::string& aString) { myA = A(aString);}
private:
A myA;
};
int main()
{
B b;
std::string hello;
b.InitMembers(hello);
}
谢谢:)
【问题讨论】:
-
似乎有点类似于:stackoverflow.com/a/31213816/754407,“如果它有名字,它就是一个左值引用”。查看
Aclass ctor:你必须使用std::move,因为值被命名,它可以被多次使用,因此你必须明确它。std::move是一个“右值转换”,但类型推导仅在使用模板类型T&&时才会发生,然后它可以绑定到任一类型的引用,std::move可以同时处理两者。 -
"为什么我还必须在 A 的构造函数初始化器中使用 std::move?" -- 因为
string&& aString是“对 r 值的引用”,它本身就是一个 l -值。 -
嗨@Tharsalys,您遇到了我的一个疑问,为什么它是LValue?我的意思是,如果我说“aString”是作为 RValue 引用提供的,但它实际上是 LValue,我说得对吗? RValue 引用是否在范围内被视为左值(在这种情况下它是初始化列表)?
-
@Evethir,
aString是一个左值,因为“它是一个有名字的东西”。 -
嗨@TedLyngmo 我已经清理了代码,希望现在更清楚:)
标签: c++ rvalue-reference lvalue perfect-forwarding stdmove