C++ move semantics

move semantics

C++11中引入了move semantics,它是基於[rvalue reference](C++ lvalue,rvalue及rvalue reference)來優化物件搬移效率的一種機制。

在一個自定義的類別中,如果我們希望使用move semantics,就必須為它定義兩個成員函數:move constructor及move assignment operator。

move constructor

move constructor的核心理念是:

  1. 把temporary object中的資料給搬到新物件中
  2. 將temporary object還原到一個valid state(可以想成0或NULL)

TensorRT/samples/common/buffers.h中:

//move constructor
//此處的GenericBuffer&&就是rvalue reference
GenericBuffer(GenericBuffer&& buf)
    //獲取temporary object的成員屬性
    : mSize(buf.mSize)
    , mCapacity(buf.mCapacity)
    , mType(buf.mType)
    , mBuffer(buf.mBuffer)
{
    //將temp object還原到一個valid state
    buf.mSize = 0;
    buf.mCapacity = 0;
    buf.mType = nvinfer1::DataType::kFLOAT;
    buf.mBuffer = nullptr;
}

注意此處move constructorGenericBuffer(GenericBuffer&& buf)的輸入是一個rvalue reference。

第一步先將buf的屬性給搬到新物件中,第二步則是將傳入的參數buf清空,注意因為這裡是右值引用,所以我們才可以修改buf

move assignment operator

move assignment operator裡包含三步驟,相較於move constructor多了一步,即一開始需要將其現在的資料給清空:

  1. 把現有資料清空
  2. 把temporary object中的資料給搬到新物件中
  3. 將temporary object還原到一個valid state(可以想成0或NULL)

同樣來自TensorRT/samples/common/buffers.h

//move assignment operator
GenericBuffer& operator=(GenericBuffer&& buf)
{
    if (this != &buf)
    {
        //清理現有的資料
        freeFn(mBuffer);
        //從temporary object中獲取資料
        mSize = buf.mSize;
        mCapacity = buf.mCapacity;
        mType = buf.mType;
        mBuffer = buf.mBuffer;
        // Reset buf.
        //將temporary state還原到一個valid state
        //注意!在使用move assignment operator時等號右邊的GenericBuffer物件會被reset!
        buf.mSize = 0;
        buf.mCapacity = 0;
        buf.mBuffer = nullptr;
    }
    return *this;
}

vector::emplace_back(move(unique_ptr))

同樣來自TensorRT/samples/common/buffers.h

//std::vector<std::unique_ptr<ManagedBuffer>> mManagedBuffers; //!< The vector of pointers to managed buffers
//std::unique_ptr<ManagedBuffer> manBuf{new ManagedBuffer()};
mManagedBuffers.emplace_back(std::move(manBuf));

由於manBuf是unique_ptr,所以它不能被複製。
如果使用 v.emplace_back(manBuf)的寫法,根據std::vector::emplace_back with lvalue expression它實際上會複製一份manBuf再將它放入向量中,所以這肯定是會報錯的。

move semantics的存在讓我們可以移交物件的所有權而不需要另外複製一份。
為了使用move semantics,我們必須先將manBuflvalue轉換為rvaluervalue默認使用move semantics),而這就是std::move(manBuf)在這裡的意義。以下是std::move的定義:

template <class T>
typename remove_reference<T>::type&& move (T&& arg) noexcept;

它的作用是回傳其參數arg的rvalue reference。

vectoremplace_back的參數正好是rvalue reference:

template <class... Args>
  void emplace_back (Args&&... args);

兩者正可遙相呼應。

參考連結

C++ rvalue references and move semantics for beginners

Why is move necessary with emplace_back in this example?

Pushing an object with unique_ptr into vector in C++

std::vector::emplace_back with lvalue expression

std::move

std::vector::emplace_back

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值