2017-02-09 93 views
5
#include <iostream> 
#include <string> 
#include <array> 

class C { 
private: 
    std::string a; 
    std::string b; 
    std::string c; 
public: 
    C(std::string a_, std::string b_, std::string c_) : a{a_},b{b_},c{c_} {} 
    ~C(){}; 
    C(const C&) =delete; 
    C(const C&&) =delete; 
    const C& operator=(const C&) =delete; 
    const C& operator=(const C&&) =delete; 
}; 

std::array<C,2> array = {C("","",""),C("","","")}; 

int main() 
{} 

這將不會編譯(Android Studio與NDK和鏗鏘)與「調用刪除C構造函數」錯誤。我知道我可以使用std::vectoremplace_back()直接在容器內構建元素,但在我的代碼中,我只想使用固定大小的容器和不可複製/可移動的對象進行優化。我可能在這裏缺少基本的東西,但是沒有辦法初始化std::array而無需先構建單個元素然後將它們複製到那裏?初始化std :: array沒有複製/移動元素

+2

通過你不需要把這些下劃線在參數名的方式。 'C(std :: string a,std :: string b,std :: string c):a {a},b {b},c {c} {}'沒有歧義問題,並且符合您的期望。 – nwp

回答

6

你可以用括號括初始化,而不是臨時c對象:

std::array<c,2> array = {{{"",""},{"",""}}}; 

std::array<c,2> array{{{"",""},{"",""}}}; 
+0

它是一種便攜式解決方案嗎?我的意思是取決於std :: array是如何實現的,它必須包含一個'T [N]'類型的元素。 – marcinj

+0

@marcinj我很確定。上次我檢查了這個要求並不是'std :: array'只包含'T [N]'類型的一個元素,但它的行爲就像它一樣。關於中間'{}'是否可以省略是一個完整的問題,也就是說這是否也應該是有效的:'{{「」,「」},{「」,「」}}'。自C++ 11以來,最後一件事可能已經發生了變化。 – juanchopanza

+0

我在問,因爲我正在閱讀一篇SO,T.C.說它不保證:http://stackoverflow.com/questions/27669200/how-should-i-brace-initialize-an-stdarray-of-stdpairs#comment43754338_27669457。 – marcinj

5

因爲C++ 17它將成爲可能,對於某些特定情況下copy elision保證。

在下列情況下,需要編譯器省略 的複印通和類的構造函數MOVE-對象即使複製/移動 構造函數和析構函數具有可觀察到的副作用:

  • 在初始化過程中,如果初始化表達式是一個prvalue,並且源類型的cv不合格版本與目標類的 類相同,則初始化表達式用於初始化目標對象 :

    T x = T(T(T())); // only one call to default constructor of T, to initialize x 
    

而對於這些情況,複製/移動構造不需要訪問。

When copy-elision takes place (until C++17)In those cases where copy-elision is not guaranteed, if it takes place (since C++17)和 的禁止複製/移動構造函數不叫,它必須存在和 訪問(因爲如果沒有優化發生在所有),否則病形成的 程序。

LIVE