2011-08-19 78 views
7

可以給靜態數組定義一個初始化列表。例如:動態數組的初始化列表?

int main() 
{ 
    int int_static[2] = {1,2}; 
} 

動態數組是否有類似的初始值設定項列表?

int main() 
{ 
    int* int_ptr = new int[2]; 
} 

這更接近我所試圖做的:

struct foo 
{ 
    foo(){} 
    foo(void * ptr): ptr_(ptr) {} 
    void * ptr_; 
}; 

int main() 
{ 
    foo* foo_ptr = new foo[10]; 
} 

在初始化時沒有默認的構造函數應該叫,但FOO:FOO(無效*)。

有一個動態數組的靜態初始值設定項列表可能會適用於即時編譯加速器核心的情況,這些加速器核心只有有限的堆棧可用,但同時您構建(加速器編譯時間=主機運行時間)靜態初始化程序列表。

我假設沒有(因爲這需要編譯器生成額外的代碼,即將參數的值複製到堆位置)。我認爲C++ 0x支持這一些,但我不能使用它。 現在我可以使用這樣的構造。也許有人知道一招......

最好!

回答

9

不,你不能那樣做。

我認爲C++不允許這樣做,因爲允許這樣的事情不會添加任何好的功能的語言。換句話說,如果您使用靜態初始化程序初始化它,那麼動態數組的點會是什麼?

動態數組的點是根據實際需要在運行時創建一個大小爲N的數組,它是已知的。也就是說,代碼

int *p = new int[2]; 

意義不大我比下面

int *p = new int[N]; //N is known at runtime 

如果是這樣,那麼你怎麼能提供在靜態初始化因爲N元素的數量直到運行時才知道?

讓我們假設,你可以寫這樣的:

int *p = new int[2] {10,20}; //pretend this! 

但是你寫這得到什麼大的優勢?沒有。它幾乎一樣:

int a[] = {10,20}; 

,當你可以寫,對於N元素的數組的真正好處是。但問題是這樣的:

int *p = new int[N] {10,20, ... /*Oops, no idea how far we can go? N is not known!*/ }; 
+4

爲了記錄,「動態」並不意味着「可變長度」。這確實是一個「很好的功能」,能夠創建一個新的動態對象並將其初始化爲已知的初始內容。這正是構造函數爲類和結構類型對象所做的。 –

+0

爲了澄清,C++中的'dynamic'意味着分配在堆上而不是堆棧上。我廣泛使用兩個存儲器商店,因此有兩個初始化器列表工作將非常方便。就像在許多情況下,當我想在堆上創建一個數組列表時,我不得不求助於對象(比如std :: vector)而不是普通數組,因爲@MikeHousky說,C++只支持在堆上初始化對象那一刻,不是陣列。這裏沒有技術或性能問題 - 只是C++的限制。 – holocronweaver

0

無論如何,初始化程序的數據必須在某處。簡單地命名它。

例如,

#include <stddef.h> 
#include <algorithm>  // std::copy 
#include <vector> 

typedef ptrdiff_t Size; 

template< class Type, Size n > 
Size countOf(Type (&)[n]) { return n; } 

int main() 
{ 
    using namespace std; 

    static int const initData[] = {1,2}; 
    static Size const n   = countOf(initData); 

    // Initialization of a dynamically allocated array: 
    int*  pArray = new int[n]; 
    copy(initData, initData + n, pArray); 

    // Initialization of a vector: 
    vector<int> v(initData, initData + n); 
} 

EDIT:固定在上面的代碼中一個thinko。我趕緊在請求中添加示例。所以我所做的錯誤地使用了從std::copy返回的值。

乾杯&心連心,

+0

這不是特別清楚。你能舉一個說明性的例子嗎? –

+0

@Oli,我想他指的是類似於我在答案中建議的解決方案,只是忽略了所需副本的血淋淋的細節。 –

+0

好的,完成了。我不明白什麼不清楚。 –

2

不,你將不得不動態創建的元素。

或者,也可以使用本地陣列和對這些動態分配的陣列的複製其元素:

int main() { 
    int _detail[] = { 1, 2 }; 
    int * ptr = new int[2]; 
    std::copy(_detail, _detail+(sizeof detail/sizeof *detail), ptr); 
    delete [] ptr; 
} 

在設置爲0的所有元素的有限版本中,可以使用一個額外的一對括號的在new電話:

int * ptr = new int[2](); // will value initialize all elements 

但你似乎在尋找不同的東西。

+0

第一句話中的標點符號有點誤導;有「固定」。如果您不同意,請回滾。 –

+0

我正在尋找一種方式來調用動態分配的每個元素的構造函數(當然它不只是一個「int」)。但它不是必須調用的標準構造函數。它必須採用1個參數,並且該參數的左值對每個元素都是不同的。 – ritter

+0

不應該_detail是一個int *? –

0

鑑於你是真實的類比int更復雜,並且由不同的值構造,它很複雜。 如果您的現有數組/矢量具有默認值的正確值,或者您必須使用放置位置新,則可以使用迭代器構建矢量。

//vector 
int main() 
{ 
    int int_static[2] = {1,2}; 
    std::vector<int> int_dynamic(int_static, int_static+2); 
    //this is what everyone else is saying. For good reason. 
} 
//placement new 
int function_that_returns_constructed_from_values() { 
    return rand(); 
} 
int main() 
{ 
    int count = 2; 
    char *char_dynamic = new char[count * sizeof(int)]; 
    int *int_dynamic = char_dynamic; 
    for(int i=0; i<count; ++i) 
     new(int_dynamic+i)int(function_that_returns_constructed_from_values()); 
    //stuff 
    for(int i=0; i<count; ++i) 
     (int_dynamic+i)->~int(); //obviously not really int 
    delete []char_dynamic; 
} 

顯然,向量是執行此操作的首選方法。

10

當OP發佈這個問題時,C++ 11支持可能還不是很流行,這就是爲什麼接受的答案說這是不可能的。但是,現在應該在所有主要的C++編譯器中支持使用顯式初始化列表初始化動態數組。

語法new int[3] {1, 2, 3}在C++ 11中被標準化。引用上cppreference.com的new expression頁:

由新的表達產生的目的根據下列規則進行初始化:
...
如果類型是數組類型,一個初始化對象陣列:
...
如果初始化程序是一個括號括起來的參數列表,則該數組將被聚合初始化。 (因爲C++ 11)

因此,鑑於OP的例子,以下用C++ 11或更高版本時,是完全合法的:

foo * foo_array = new foo[2] { nullptr, nullptr }; 

注意通過在初始化列表中提供指針,我們實際上是在哄騙編譯器來應用foo(void * ptr)構造函數(而不是默認的構造函數),這是所需的行爲。