簡體   English   中英

在另一個對象構造函數中初始化不可復制的不可移動對象的數組

[英]Initialize array of non-copyable non-movable objects in another objects constructor

這個問題與數組初始化和SystemC模塊層次結構有關。

我有一個不可復制,不可移動且沒有默認構造函數的類:

class Object : public sc_module {
    public:
      Object(string name, Configuration config);
      Object(const CPU& that) = delete;

};

另一個具有這些數組的類:

class Object2 : public sc_module {
    public:
      std::array<Object, 2> obj_array;
      Object2() : obj_array <--??--> 
      {}
};

我需要使用Objects初始化obj_array ,該Objects不能被復制並且不能被移動。

我已經嘗試了很多組合,並且編譯的一件事是:

class Object2:  {
    public:
      std::array<Object, 2> obj_array;
      //note the double braces on this initializer list
      Object2() : obj_array {{ {"string1", config}, {"string2", config} }} 
      {}
};

它可以工作,但是我稍后會在代碼中看到一些奇怪的行為:當我在obj_array打印Objects的名稱時,第一個是正確的Object2.string1但是下一個是真正奇怪的Object2.string1.string2當它應該只是Object2.string2 )。

我知道很多人都問過類似的問題,但是我想弄清楚這里到底發生了什么。 在我看來,我似乎在該初始化程序列表中花了太多括號,但否則將無法編譯。

我正在使用帶有標志-std = c ++ 14的g ++ 6.4.0

問題是如果我在構造函數的主體中創建另一個數組,例如,類Object2:{public:std :: array obj_array; // //注意此初始化程序列表上的雙括號Object2():obj_array {{{“ string1”,config},{“ string2”,config}}} {Obj arr [2] {{“ test”,config},{ “ test2”,config}}; };

一切似乎都正常。 arr對象名稱及其父母都是正確的。

我知道這是一個深奧的問題,但是我需要幫助來了解我的obj_array初始化過程中到底發生了什么機制。

大括號加倍的形式是初始化std::array的“完成”方式,因為std::array實際上是包含原始C樣式數組的聚合結構。 本質上是

namespace std {
    template <class T, size_t N>
    struct array {
        T __some_internal_name[N];

        // public members...
    };
}

因此初始化如下:

std::array<int, 3> A{{ 2, 3, 4 }};

之所以有效,是因為外部{}用於std::array結構對象,內部{}用於其包含的原始C樣式數組。

通常情況下 ,不需要雙括號,因為有一條規則允許您為另一個聚合中的某個聚合忽略一些嵌套的括號。 這就是為什么初始化如下:

std::array<int, 3> A{ 2, 3, 4 };

與上述相同。

規則是,如果下一個子對象也是一個聚合(至少包含一個子集),則當編譯器將初始化列表的各個部分與聚合的子對象(結構/類的非靜態數據成員或數組的元素)相關聯時,一個初始化子列表中的下一個子對象不是以{標記開頭的,則該子對象從初始化子列表中抽取了盡可能多的子對象,因為它擁有自己的直接子對象。 但是,如果初始化列表中的下一個內容以{開頭,則假定它是該聚合子對象的完整初始化列表。

因此,如果您擁有幾乎正確的代碼

Object2() : obj_array { {"string1", config}, {"string2", config} }
   {}

編譯器將如下處理:

  1. obj_arraystd::array<Object, 2> ,它是一個聚合結構,其初始化程序是一個帶有括號的初始化程序列表,因此適用聚合初始化。

  2. 第一個{obj_array對象關聯。

  3. obj_array有一個子對象,類型為Object[2] 此類型也是聚合類型,並且初始化列表中的下一個內容以{開頭,因此它將打開另一個初始化列表以初始化Object[2]數組。

  4. Object[2]包含兩個子對象,都屬於Object類型,這是一個非聚合類類型。

  5. 必須使用initializer-list中的下一個Object "string1"初始化第一個Object 但是沒有從const char[8]Object有效轉換。 這是一個錯誤。

此后可能還會出現其他錯誤,具體取決於編譯器嘗試繼續的方式。

簡而言之, std::array的單括號樣式在您的情況下不起作用的原因是,由於您打算成為Object初始化器的原因是以{開頭,因此它被視為C樣式的初始化器數組代替。

雙括號解決方案有效,或者您也可以指定Object類型,以避免用另一個initializer-list來啟動initializer-list元素:

Object2() : obj_array { Object{"string1", config}, Object{"string2", config} }
   {}

您的SystemC問題可能與所有這些都不相關,因為雙括號樣式是正確的,並且可以滿足您的期望。 這可能是Configuration類的詳細信息。 (請注意,構造函數采用“按值” Configuration參數,這意味着構造函數獲取的對象將是您傳遞給它的任何內容的副本,如果有關系的話。)我建議詢問一個單獨的問題,並提供有關該問題的更多詳細信息。

暫無
暫無

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

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