簡體   English   中英

C ++是否有類似RVO的東西將臨時對象傳遞給函數?

[英]C++ Is there something like RVO for passing temporary objects to functions?

使用RVO可以從返回的對象創建對象,而無需移動或復制。 將對象傳遞給函數時,是否可以做類似的事情?

class SomeClass {
    int a;

public:
    SomeClass(int _a)                   {a = _a;        std::cout << "created\n";}
    SomeClass(const SomeClass& source)  {a = source.a;  std::cout << "copied\n";}
    SomeClass(SomeClass&& source)       {a = source.a;  std::cout << "moved\n";}
};

void create(SomeClass&& source) {
    SomeClass some_object( std::move( source));
    //p_some_object = new SomeClass( std::move( source));
    //new( p_some_object) SomeClass( std::move( source));
}

// ...

create(SomeClass(15));

在此示例中,結果是“創建,移動”。 (GCC 5.4 / C ++ 11 / -O3)與new或place-new相同。 沒有分支或任何分支,那么為什么不移動就不能創建它?

無法保證編譯器必須進行內聯和分析,以識別出由source引用的臨時對象是不必要的。 除此之外,甚至RVO也用於值語義。 &&引用起作用時,不能保證。

碰巧的是,如果您遵循C ++函數參數的一般規則,那么GCC可以很好地處理您的情況: “如果仍然需要復制參數,請按值接受參數。”

按值接受表示在這種情況下將參數構造為調用的一部分的情況下,不需要復制或移動(在GCC上可以是“ RVO” -ed)。

class SomeClass {
    int a;

public:
    SomeClass(int _a)                   {a = _a;        std::cout << "created\n";}
    SomeClass(const SomeClass& source)  {a = source.a;  std::cout << "copied\n";}
    SomeClass(SomeClass&& source)       {a = source.a;  std::cout << "moved\n";}
};

void create(SomeClass some_object) {

}

int main() {
    create(SomeClass(15));
}

如果嘗試使用 ,則僅顯示created消息。

如果目標是create以為您構造對象,則使用帶有參數轉發功能的模板化函數,以便在create內構造它,例如

template<typename T, class... Args>
T create(Args&&... args) {
    T some_object(std::forward<Args>(args)...);

    return some_object;
}

int main() {
    auto foo = create<SomeClass>(15);
}

它通過傳遞構造函數參數作為轉發引用來解決問題,並在create內部構造對象本身,避免了任何額外的構造, 如此處所示

RVO不會與引用一起發生,也不會在通過函數參數創建另一個對象時發生。

如果將引用參數更改為值參數,則會將RVO應用於它,而不是本地對象:

void create(SomeClass source) { 
    SomeClass otherObject = std::move(source); // No RVO, object constructed from parameter
}

// ...    

create(SomeClass{15}); // RVO applied to source parameter

但是,您可以使用lambda作為函數參數來實現它:

template<typename C>
void create(C source) {
    SomeClass some_object{source()};
}

// ...

create([]{ return SomeClass{15}; });

您可以檢查實時輸出

暫無
暫無

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

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