簡體   English   中英

具有左值表達式的std :: vector :: emplace_back

[英]std::vector::emplace_back with lvalue expression

emplace_back與某些struct S左值一起使用是否真的有意義:

像這樣:

std::vector<S> v;
auto s = S(/*...*/);
v.emplace_back(s);

而不僅僅是:

v.emplace_back(/* S constructor arguments */);

或者它只是簡單地濫用emplace_back ,只是因為const S& (以及復制構造函數)是emplace_back Args... args合法實例,並且它不是明確禁止的嗎?

正如您已經說過的,傳遞const S&只會調用復制構造函數。

除非你打算在將它傳遞給emplace_back之前以某種方式使用s ,否則它不一定是明智的。

但是,如果創建s的代碼特別長,它可以提高將它和emplace_back的代碼放在不同行上的可讀性。 編譯器非常擅長優化這種情況,並且可能會生成相同的代碼(如果復制構造函數是默認的)。 基本示例: https//godbolt.org/z/D1FClE

如果它提高了可讀性或可維護性,那么它就沒有價值。

如果稍后在代碼中不需要s ,那么它是對emplace_back()函數的誤用。 這是因為您正在調用S類的復制構造函數,而不是將參數傳遞給emplace_back() ,后者將使用S的正確構造函數。

請考慮以下代碼:

#include <iostream>
#include <vector>

struct S
{
    S()          {std::cout<< "     default ctor" <<std::endl;}
    S(int)       {std::cout<< "     user-def ctor" <<std::endl;}
    S(const S &) {std::cout<< "     copy ctor" <<std::endl;}
    S(S &&)      {std::cout<< "     move ctor" <<std::endl;}
};

int main()
{
    std::vector<S> v;
    v.reserve(5);

    std::cout<< "auto calls: " <<std::endl;
    auto s = S();
    std::cout<<std::endl;

    std::cout<< "emplace_back( s ) calls: " <<std::endl;
    v.emplace_back(s);
    std::cout<<std::endl;

    std::cout<< "emplace_back( std::move(s) ) calls: " <<std::endl;
    v.emplace_back(std::move(s));
    std::cout<<std::endl;

    std::cout<< "emplace_back( S{} ) calls: " <<std::endl;
    v.emplace_back(S{});
    std::cout<<std::endl;

    std::cout<< "emplace_back( ) calls: " <<std::endl;
    v.emplace_back();
    std::cout<<std::endl;

    std::cout<< "emplace_back( 2 ) calls: " <<std::endl;
    v.emplace_back(2);
    std::cout<<std::endl;
}

結果是:

auto calls: 
     default ctor

emplace_back( s ) calls: 
     copy ctor

emplace_back( std::move(s) ) calls: 
     move ctor

emplace_back( S{} ) calls: 
     default ctor
     move ctor

emplace_back( ) calls: 
     default ctor

emplace_back( 2 ) calls: 
     user-def ctor

儲備用於為5分配空間S秒。 如果不保留空間,輸出將包括從向量中復制ctors的附加調用。

當你只是將參數傳遞給S的構造函數(在這種情況下,沒有)時, emplace_back()使用直接在向量內部的默認ctor創建一個S對象。

順便說一下,看看godbolt中的例子,在這些情況下,你的朋友可以看到背景中發生了什么。

暫無
暫無

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

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