簡體   English   中英

在這個例子中為什么需要使用emplace_back進行移動?

[英]Why is move necessary with emplace_back in this example?

當使用選項1或選項2下的代碼時,以下最小工作示例進行編譯,但在使用選項3下的代碼時編譯。 我假設emplace_back()隱式使用/調用move構造函數,那么為什么需要顯式move()呢? 它與r-valuel-value嗎? 或者這與std::unique_ptr需要轉移所有權有關嗎? (我仍然對這些概念不熟悉,特別是在這種情況下。)

為了完整性,除非調用move() ,否則帶有push_back()選項4也不會編譯。

#include <iostream>
#include <vector>
#include <memory>

class Beta {
public:
    Beta(int x, int y, int z): mX(x), mY(y), mZ(z) { };
    int mX; int mY; int mZ;

};

class Alpha {
public:
    std::vector<std::unique_ptr<Beta>> betaVec;
    void addBeta(int x, int y, int z) {
        // only choose one of the following options:
        // option 1 (compiles)
        std::unique_ptr<Beta> pBeta = std::make_unique<Beta>(x, y, z);
        betaVec.emplace_back(move(pBeta));

        // option 2 (compiles)
        betaVec.emplace_back(std::make_unique<Beta>(x, y, z));

        // option 3 (does not compile)
        std::unique_ptr<Beta> pBeta = std::make_unique<Beta>(x, y, z);
        betaVec.emplace_back(pBeta);

        // option 4 (does not compile)
        std::unique_ptr<Beta> pBeta = std::make_unique<Beta>(x, y, z);
        betaVec.push_back(pBeta);

        // option 5 (compiles)
        std::unique_ptr<Beta> pBeta = std::make_unique<Beta>(x, y, z);
        betaVec.push_back(move(pBeta));
    }
};

int main() {

    return 0;
}

注意:我不認為這是關於將unique_ptr參數傳遞給函數的這個問題的重復,即使鏈接問題的答案很有用,因為這要求函數中定義unique_ptr然后將其移動到成員vector以便它不會在函數結束時被銷毀,而且,在此上下文中具體詢問emplace_back()

另外,我認為在這種情況下給出解釋是有用的,因為有時很難將解釋從一個上下文轉換到另一個上下文。 謝謝!

我假設emplace_back()隱式使用/調用移動構造函數

對不起,但你的假設是錯的。 emplace_back構造了向量中的對象,即不是從對象中復制/移動對象,而是直接構造元素,避免了復制/移動構造函數。

現在,如果您使用相同(但另一個)對象構造對象,那么當然要使用復制或移動構造函數,這就是您的情況。

那么為什么需要一個明確的move()

因為你無法復制std::unique_ptr 基本上, emplace_back做了類似於此的事情:

new (place) T(std::forward<Ts>(args)...);

就像你做的那樣: T a(std::forward<Ts>(args)...) (僅用於構造,它實際上並沒有做同樣的事情)。

現在它可能更明顯一點:

T option1(std::move(pBeta)); // ok, move
T option3(pBeta); // error, copy

它與r-valuel-value嗎? 或者這與std::unique_ptr需要轉移所有權有關嗎?

那么,在某種程度上,是的。 std::unique_ptr需要明確的所有權轉移,這就是為什么副本被禁用而移動不是(你仍然希望轉移所有權!並且副本可以在任何地方發生 - 為什么std::auto_ptr被棄用,然后被刪除)。 右值默認使用移動語義,而左值則不使用移動語義。 通過使用std::move ,您正在進行從左值到初值的轉換,有效地“隱藏”您擁有左值的事實,編譯器將很樂意從它移動。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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