假設我在記憶體中有一個包含 c_string 的字符緩沖區,并且我想以有效的方式將std::string具有該 c_string 內容的物件添加到標準容器中,例如std::list<std::string>。
例子:
#include <list>
#include <string>
int main()
{
std::list<std::string> list;
char c_string_buffer[] {"For example"};
list.push_back(c_string_buffer); // 1
list.emplace_back(c_string_buffer); // 2
list.push_back(std::move(std::string(c_string_buffer))); // 3
}
我使用 ReSharper C ,它抱怨 #1(并建議 #2)。
當我閱讀push_back vs emplace_back時,它說當它不是右值時,容器將存盤“復制”副本,而不是移動副本。意思是,#2 與#1 相同。不要盲目地喜歡 emplace_back 而不是 push_back也談到了這一點。
案例3:當我讀到搬家有什么問題?,它說std::move()“是對右值參考的強制轉換,這可能會在某些條件下移動”。
--
#3 真的有什么好處嗎?我假設呼叫了的建構式并使用 c_string 的內容std::string創建了一個物件。std::string我不確定以后容器是否構造另一個std::string并將第一個物件復制到第二個物件。
uj5u.com熱心網友回復:
// 3完全等價于// 1。std::move在這里絕對什么都不做,因為std::string(c_string_buffer)它已經是一個右值。
問題與push_back移動與復制無關。
push_back如果您還沒有元素型別的物件,則始終是一個糟糕的選擇,因為它總是通過復制或移動來自另一個元素型別物件的構造來創建新的容器元素。
如果您撰寫list.push_back(c_string_buffer); // 1,那么因為push_back需要一個std::string&&引數(或const std::string&),所以型別的臨時物件std::string將從 構造c_string_buffer并通過參考傳遞給push_back。push_back然后從這個臨時構造新元素。
與// 3您一起只是進行臨時構造,否則會隱式顯式發生。
上面的第二步可以完全避免emplace_back。它不是參考目標型別的物件,而是通過參考獲取任意引數,然后直接從引數構造新元素。不需要臨時std::string的。
uj5u.com熱心網友回復:
3真的有什么好處嗎?
沒有。 #1 已經在沒有std::move. #3 只是寫 #1 的一種不必要的顯式方式。
#2通常可能是最有效的。這就是你的靜態分析器建議它的原因。但是,正如文章所解釋的,在這種情況下它并不重要,并且有潛在的編譯時損失。我相信你可以通過使用來避免潛在的編譯時間成本list.emplace_back( c_string_buffer);,但這可能會讓讀者感到困惑。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/438739.html
上一篇:在浮點值中獲得平方根的最快方法
下一篇:選擇具有特定值的重復行
