2010-09-02 138 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