Move and Forward cases use
Move and Forward cases use
我跟随本教程开始理解c++ 11中的移动语义和右值引用。在某些时候,他用move构造函数中的std::move
实现了这两个类,解释了
传递给move构造函数,它就有了新的生命在新的范围内。在右值表达式所在的上下文中求值后,临时对象就真的结束了。但在我们的构造函数,对象有一个名字;它将是活的函数的整个持续时间。换句话说,我们可以用其他变量在函数中不止一次出现,并且是临时的对象具有一个定义的位置,该位置在整个对象中真正持续存在函数。它是术语定位器值
真正意义上的左值
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移动构造函数中,我试图用std::forward<MetaData>
改变std::move
,代码显示,如果我调用ArrayWrapper移动构造函数,这将调用元数据移动构造函数,如std::move
的示例。
当然,如果我不使用std::move
或std::forward
,元数据复制构造函数将被调用。
问题是,在这种情况下,使用std::move
和std::forward
之间有区别吗?为什么我要用一个而不用另一个呢?
使用std::move和std::forward有区别吗?为什么我要用一个而不用另一个呢?
是的,std::move
返回其参数的右值引用,而std::forward
只是转发参数,保留其值类别。
使用move
当你明确想要转换为右值。当你不知道你有什么(可能是左值或右值),并希望完美地转发它(保留它的l或r值)时,使用forward
。我可以通常/总是使用std::forward而不是std::move吗?是一个你可能会感兴趣的问题。
在下面的代码片段中,bar
将获得foo
的调用者传递的内容,包括保留的值类别:
template <class T>
void foo(T&& t) {
bar(std::forward<T>(t));
}
不要让T&&
欺骗了你——t
不是右值引用。当它出现在类型推断上下文中时,T&&
获得了特殊的含义。当foo
实例化时,T
取决于传递的参数是左值还是右值。如果是类型为U
的左值,则将T
推导为U&
。如果是右值,则T
推导为U
。有关详细信息,请参阅这篇优秀的文章。您需要了解值类别和引用折叠,以便更好地理解这方面的内容。
相关的std::forward
和std::move
声明为:
template< class T >
T&& forward( typename std::remove_reference<T>::type& t );
template< class T >
typename std::remove_reference<T>::type&& move( T&& t );
对于前者:
std::forward<MetaData>(other._metadata);
std::forward<MetaData>
返回MetaData&&
对于后者:
std::move(other._metadata);
//argument derived as lvalue reference due to forwarding reference
std::move<MetaData&>(other._name);
std::move<MetaData&>
返回typename std::remove_reference<MetaData&>::type&&
,即MetaData&&
。
所以这两种形式在你的例子中是相同的。然而,std::move
在这里是正确的选择,因为它显示了我们无条件移动参数的意图。std::forward
可以使用无条件移动,但它的目的是完善其参数。
- 如何处理 c++ 中类实现中的"invalid use of non-static data member"?
- C++ "error: invalid use of void expression"
- 我看到"use of undeclared identifier"错误,有人可以告诉我如何解决它吗?
- 收到错误"invalid use of non-static data member 'stu::n' "
- 模式"allocate memory or use existing data"
- C++ "error: use of overloaded operator '*' is ambiguous"似乎只有一场比赛
- Is it good to use SDL_PIXELFORMAT_UNKNOWN?
- C++ "Invalid use of 'this' in non-member function" ,
- std::launder use cases in C++20
- 继承类时"invalid use of incomplete type ‘class tree_node_t’"
- "reserved for any use"的含义是什么?
- C++14 遇到奇怪的"use of deleted function"错误
- C++ 中的 use 函数是什么?
- 出现这种错误的原因是什么"invalid use of non-static data member "
- 模板类和'invalid use of incomplete type'错误
- 为什么"non-standard syntax; use '&' to create a pointer to member"在 CTOR 中使用线程?
- "invalid use of incomplete type" .解决循环依赖关系
- Use cases of mmap
- Move and Forward cases use
- Use cases for std::error_code