2010-09-02 112 views
1

我想創建一個foo的動態數組,其中的項數是x。參數y和z將被傳遞給項目foo的構造函數。我希望做類似的東西:動態數組初始化

Foo* bar = new Foo(y, z)[x]; 

但是所產生以下編譯器錯誤:

error: expected `;' before '[' token 

因此,與有經驗的朋友說後,他給了我這一點,他承認是一個懶散的這樣做的方式,但它的作品。我想知道,有沒有更好的/正確的方法?

Foo* bar = (Foo*) new int[x]; 
for (int i = 0; i < x; i++) { 
    bar[i] = Foo(y, z); 
} 
+6

你和你的朋友應該得到一個[好書](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list)以獲得理解的良好基礎。我的意思是說第二個代碼塊是錯的,爲什麼要分配'int'然後投射到'foo'?這幾乎可以肯定是未定義的行爲。 – GManNickG 2010-09-02 17:25:54

回答

11

「我想做一個動態數組」因此,使用std::vector,它存在的原因。

std::vector<foo> bar(x, foo(y, z)); 

這產生與初始化爲foo(y, z)x元件動態數組。


上面使得副本的第二個參數的x次。如果你想產生的vector值,使用generate_n

std::vector<double> weights; 
std::generate_n(std::back_inserter(weights), x, ...); 

更換了...與函數或仿函數調用,返回一個值。一般來說,你做一個仿函數:

struct generate_weight 
{ 
    double operator()() const 
    { 
     return random(1e-3); 
    } 
}; 

,並提供:

std::generate_n(std::back_inserter(weights), x, generate_weight()); 

如果你的編譯器支持C++ 0x中,你可以利用拉姆達的的。這些做同樣的事情,除非他們保持代碼的簡潔和本地化:

std::generate_n(std::back_inserter(weights), x, 
       [](){ return random(1e-3); }); 
+0

雖然這個工作正常,但在本例中它返回數組中所有項的相同數字: std :: vector 權重(x,random(1e-3)); – dcousens 2010-09-02 17:41:11

+0

@Daniel:確實如此,它將它初始化爲'foo(y,z)'的'x'副本。你的問題什麼都沒說;提出真正的問題以獲得真正的答案。我已經更新了我的答案。 – GManNickG 2010-09-02 17:55:20

+0

我只是想看看這是否是預期的行爲,在此之前對STL沒有經驗。我以隨機(1e-3)爲例。 感謝您的延伸答覆。 – dcousens 2010-09-02 18:12:38

1

如果你想每個元素初始化爲相同的值,然後做的GMAN建議以上:

std::vector<foo> bar(x, foo(y, z)); 

你會有一個X元素的向量,每個元素都具有相同的foo(y,z);

如果你想要每個foos的唯一值,你需要在循環中初始化它。一個簡單的例子是:

std::vector<foo> bar; 

    for (int i = 0; i < x; ++i) 
    { 
     // initialize X foos with different values for each foo. 
     bar.push_back(foo(i, random(i))); 
    } 
0

如果你堅持不使用std,至少應該這樣做。這不安全並且存在大對齊問題。

size_t x = 10; 
foo * bar= static_cast<foo*> (::operator new (sizeof(foo)* x)); 
for (size_t i=0; i<x; ++i) 
{ 
    new (&bar[i]) foo (1,1); 
} 

::operator delete (bar); 
+1

這裏沒有對齊問題,'operator new'返回最大對齊的內存塊。 – GManNickG 2010-09-02 17:58:18

+0

@GMan - 恐怕不會忽略foo的對齊。 – 2010-09-02 18:13:24

+1

同樣,沒有對齊問題。 §3.7.3.1/ 2:「...返回的指針必須適當對齊,以便它可以轉換爲任何完整對象類型的指針,然後用於訪問分配的存儲中的對象或數組...」 – GManNickG 2010-09-02 18:32:40

1

首先,您可以在數組new-expressions中使用的唯一初始化程序是()。所以,如果你想使用新的表達

foo *bar = new foo[x]; // 1. no initializer 
foo *bar = new foo[x](); // 2. `()` initializer 

根據foo是如何定義這些是你唯一的選擇,這兩種行爲可能相同或不同。其次,由於無法在new表達式中傳遞構造函數參數(y,z),所以必須默認構造數組(如上所示),然後使用賦值爲數組元素指定特定值。爲此,您的foo必須是默認可構建和可複製分配的。該代碼看起來很像你的「經驗豐富的朋友」建議的,但適當的類型(而不是int)。你現在擁有的是無用的(int從哪裏來?)。很有可能你誤解了你的經驗豐富的朋友。這是它應該是怎樣看

foo *bar = new foo[x]; 
for (int i = 0; i < x; i++) 
    bar[i] = foo(y,z); 

第三,在特定情況下std::vector會做同樣的事情在一個更優雅的方式。

+0

這是我的原始代碼,但是當使用「foo * bar = new foo [x];」時,我將必須創建一個構造函數來處理沒有參數(如您所說的,'default constructible'?)。然後重新初始化它們,正如你所做的那樣。 – dcousens 2010-09-02 18:11:29