簡體   English   中英

移動和前進案例使用

[英]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::movestd::forward ,則將調用MetaData復制構造函數。

問題是,在這種情況下,使用std::movestd::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&&具有特殊含義。 實例化fooT取決於傳遞的參數是左值還是右值。 如果它是類型U的左值,則將T推導為U& 如果是右值,則將T推導為U 有關詳細信息,請參見這篇出色的文章 您需要了解值類別參考崩潰,才能更好地理解這方面的內容。

相關的std::forwardstd::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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM