我关注了this tutorial开始理解 C++11 中的 move 语义和右值引用。
在某些时候,他用 std::move
实现了这两个类。在 move 构造函数中解释
we pass the temporary to a move constructor, and it takes on new life in the new scope. In the context where the rvalue expression was evaluated, the temporary object really is over and done with. But in our constructor, the object has a name; it will be alive for the entire duration of our function. In other words, we might use the variable other more than once in the function, and the temporary object has a defined location that truly persists for the entire function. It's an lvalue in the true sense of the term locator value
class MetaData
{
public:
MetaData(int size, const string& name)
: _name(name)
, _size(size)
{}
MetaData(const MetaData& other)
: _name(other._name)
, _size(other._size)
{
cout << "MetaData -- Copy Constructor" << endl;
}
MetaData(MetaData&& other)
: _name(move(other._name))
, _size(other._size)
{
cout << "MetaData -- Move Constructor" << endl;
}
~MetaData()
{
_name.clear();
}
string getName() const { return _name; }
int getSize() const { return _size; }
private:
string _name;
int _size;
};
class ArrayWrapper
{
public:
ArrayWrapper()
: _p_vals(new int[64])
, _metadata(64, "ArrayWrapper")
{}
ArrayWrapper(int n)
: _p_vals(new int[n])
, _metadata(n, "ArrayWrapper")
{}
ArrayWrapper(ArrayWrapper&& other)
: _p_vals(other._p_vals)
, _metadata(move(other._metadata))
{
cout << "ArrayWrapper -- Move Constructor" << endl;
other._p_vals = nullptr;
}
ArrayWrapper(const ArrayWrapper& other)
: _p_vals(new int[other._metadata.getSize()])
, _metadata(other._metadata)
{
cout << "ArrayWrapper -- Copy Constructor" << endl;
for (int i = 0; i < _metadata.getSize(); ++i)
_p_vals[i] = other._p_vals[i];
}
~ArrayWrapper()
{
delete[] _p_vals;
}
int* getVals() const { return _p_vals; }
MetaData getMeta() const { return _metadata; }
private:
int* _p_vals;
MetaData _metadata;
};
在 ArrayWrapper move 构造函数中,我尝试更改 std::move
与 std::forward<MetaData>
并且代码显示,如果我调用 ArrayWrapper move 构造函数,这将调用 MetaData move 构造函数,就像带有 std::move
的示例一样.
当然,如果我不使用 std::move
或 std::forward
将调用元数据复制构造函数。
问题是,在这种情况下,使用 std::move
有区别吗?和 std::forward
?为什么我应该使用一个而不是另一个?
最佳答案
is there a difference between using std::move and std::forward? Why should I use one instead of the other?
是的,std::move
返回其参数的右值引用,而 std::forward
只是转发保留其值类别的参数。
当您明确想要将某些内容转换为右值时,请使用move
。当您不知道自己拥有什么(可能是左值或右值)并且想完美地将其转发(保留其 l 或 r 值)到某物时,请使用 forward
。 Can I typically/always use std::forward instead of std::move?是您可能感兴趣的问题。
在下面的代码片段中,bar
将准确获取 foo
的调用者传递的内容,包括其保留的值类别:
template <class T>
void foo(T&& t) {
bar(std::forward<T>(t));
}
不要让 T&&
在这里骗你 - t
is not an rvalue reference .当它出现在类型推导上下文中时,T&&
具有特殊含义。当 foo
被实例化时,T
取决于传递的参数是左值还是右值。如果它是 U
类型的左值,则 T
被推导为 U&
。如果它是一个右值,则 T
被推导为 U
。参见 this excellent article了解详情。您需要了解 value categories和 reference collapsing更好地理解这方面的事情。
关于c++ - move 和转发案例使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32349944/