[英]Move and Forward cases use
我按照本教程學習了C ++ 11中的移動語義和右值引用。 在某個時候,他通過移動構造函數中的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移動構造函數,則將調用MetaData移動構造函數,如帶有std::move
的示例。
當然,如果我不使用std::move
或std::forward
,則將調用MetaData復制構造函數。
問題是,在這種情況下,使用std::move
和std::forward
有區別嗎? 為什么要使用一個而不是另一個?
std :: move和std :: forward之間有什么區別? 為什么要使用一個而不是另一個?
是的, std::move
返回其參數的右值引用,而std::forward
只是轉發保留其值類別的參數。
當您明確希望將某物轉換為右值時,請使用move
。 當您不知道所擁有的內容(可以是左值或右值)並且想要將其完美轉發(保留其左值或右值)時,請使用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
可用於無條件移動,但其目的是完善其參數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.