2017-04-23 65 views
0

爲了讓類內init選擇我想要的構造函數,似乎有必要使用類內init的賦值風格。In-class init(賦值樣式)vs構造函數的性能

class Foo { 
    // This lets me sets the vector size 
    std::vector<char> buf = std::vector<char>(BUF_SIZE); 

    // this didn't compile and made me realize finding another way to provide constructor parameters was necessary 
    // std::vector<char> buf{BUF_SIZE}; 
}; 

這是否意味着在這個風格初始化「BUF」,構建兩個對象,一個賦值運算符調用,第二個目的是破壞?或者這只是語法糖,而生成的代碼最終結果相同:

class Bar { 
public: 
    Bar() : buf(BUF_SIZE) {} 

    std::vector<char> buf; 
}; 

可能這是編譯器特定的嗎?

+2

'的std ::矢量 BUF {} BUF_SIZE'和'的std ::矢量 BUF(BUF_SIZE)'做不同的事情 - 所以你要哪一個? – UnholySheep

+1

任何好的編譯器都會隱瞞這一點,但在C++ 17中,無論如何也沒有什麼可以隱藏的。 – chris

+0

我澄清了我的帖子,指出我的目標是設置矢量的初始化大小,而不是提供任何初始值。 – Kevin

回答

0

一個好的編譯器會隱藏副本並構造一個單獨的向量。


在禁用此優化後,會發生什麼情況取決於您是否使用C++ 11支持進行編譯。我期待在這條線中特別,在沒有被一類成員的上下文(如非靜態成員初始化是一個C++ 11功能):

std::vector<char> buf = std::vector<char>(BUF_SIZE); 
  • 此前C++ 11,一個矢量將被構建(臨時),然後buf將從這個臨時版本複製構建,然後臨時被破壞。如果矢量很大,這確實是非常低效的。
  • 從C++ 11開始,臨時構建,然後buf從它移動構建; buf將從臨時數據指針中「竊取」數據指針,並使臨時數據處於未指定狀態(但有效),然後臨時數據被破壞。這個過程的開銷是微不足道的。
+1

在C++ 11之前,該語法無效。 ;-) – Jarod42

+0

好的,謝謝!總結一下:C++ 11現在允許你在類中使用賦值風格來初始化非靜態數據成員,這與初始化靜態數據成員是相似的,這一直是可以做到的。 C++ 11還增加了移動結構,使兩種情況都更加高效。根據上面的@Chris,C++ 17添加了「有保證」的省略以進一步改進:en.cppreference.com/w/cpp/language/copy_elision – Kevin