所以我只是为了解我的理解而写了一个样本和std::forward
的例子,但它并没有按照我的预期运作。在下面的程序中
#include <string>
#include <iostream>
struct A
{
A(const std::string& m) : m_(m) {};
std::string m_;
};
template<typename T>
void funcB(T&& obj) // universal reference
{
std::string local = std::move(obj.m_); // using std::move on universal reference. Bad.
std::cout << "funcB : " << local << '\n';
}
template<typename T>
void funcC(T&& obj) // universal reference
{
std::string local = std::forward<std::string>(obj.m_); // using std::move on universal reference
std::cout << "funcC : " << local << '\n';
}
template<typename T>
void funcD(T&& obj) // universal reference
{
T local = std::forward<T>(obj); // using std::move on universal reference
std::cout << "funcD : " << local.m_ << '\n';
}
int main()
{
A obj("firstString");
//funcA(obj); // We get compiler error. Rvalue reference cannot be bound to Lvalue
funcB(obj);
std::cout << "Main : " << obj.m_ << '\n';
A obj2("secondString");
funcC(obj2);
std::cout << "Main : " << obj2.m_ << '\n';
A obj3("thirdString");
funcD(obj3);
std::cout << "Main : " << obj3.m_ << '\n';
}
在输出中
funcB : firstString
Main :
funcC : secondString
Main :
funcD : thirdString
Main : thirdString
在funcC
中,即使我使用了通用引用,并且在这里绑定了Lvalue,当我执行std::forward<std::string>
时,字符串也会被移动。因此在最后一行中,在“Main:”之后没有输出。即使obj绑定到左值,也可以请某人如何移动字符串。
重读了一本书之后,刚刚意识到了答案。
在funcC中,std::forward<std::string>(obj.m_)
相当于移动字符串。
但是在funcD中,std::forward
被实例化为std::forward<struct A&>(obj)
,它被复制。
答案 0 :(得分:1)
在这两种情况下,您构造一个字符串std::string local
,并将右值引用作为参数。因此,local
是从该引用引用的原始对象移动构造的。
这与std::forward
或std::move
没有多大关系;此外,您没有初始化参考(这是&#34;将参考绑定到左值&#34;来自Meyers的文本;参考将在LHS上) - 你只是从另一个对象构造一个对象。
但是,如果不编写std::forward
或std::move
,您最终将复制这些函数参数,因为rvalue引用将在初始化方面被删除local
的声明。
因此,在这种情况下,std::forward
和std::move
具有相同的效果。但是,它们不是一回事,通常不应视为可互换。请阅读以下内容以获取更多信息: