c ++中的空动态数组

时间:2011-03-30 16:44:40

标签: c++ dynamic-arrays

假设我有一个名为Square的对象,带有构造函数Square(int rx, int ry),我想创建一个Squares的动态数组,在构造函数中有不同的参数:

Square *squares = new Square[10];  
for (int i = 0; i < 10; i++)
{
     squares[i] = new Square(i, i);
}

然而,这失败了,说没有合适的默认构造函数。那么我如何创建一个空数组或NULL数组然后再构建

编辑:由于代码中的其他内容,这必须是一个数组,这里难以解释。

9 个答案:

答案 0 :(得分:7)

使用vector。只要Square可以复制,它就没有这个问题。

vector<Square> squares;
for (int i = 0; i < 10; i++)
{
     squares.push_back(Square(i, i));
}

答案 1 :(得分:5)

您可以将指针数组创建为Square

Square **squares = new Square*[10];

for (int i = 0; i < 10; i++)
{
     squares[i] = new Square(i, i);
}

正如其他人所指出的,最好考虑使用std::vector代替。

答案 2 :(得分:1)

你应该制作一个指向SQuare的指针数组。

但是,我还建议使用std::vector而不是“经典”数组,如果Square可以复制,这是一个很好的解决方案。

但是,如果不是,或者您仍然决定使用指针方式,请将其设为std::vector shared_ptr,以便为编译器留下所有删除负担。

这会产生类似的结果:

#include <vector>
#include <boost/shared_ptr.hpp> //on some compilers, you can use #include <memory> instead

using std::vector;
using boost::shared_ptr; // or using std::shared_ptr

vector<shared_ptr<Square> > squares(10);

for (int i = 0; i < 10; i++)
{
     squares[i].reset(new Square(i, i));
}

为了更进一步,您可以查看Boost Pointer Container library

答案 3 :(得分:1)

标准库容器的工作方式是使用placement new。只使用标准库容器,如std::vector,绝对是最简单的方法。新位置是最难的。像Xeo所提到的那样,分配单个对象并保持数组中的指针位于中间。

答案 4 :(得分:1)

在适用的程序中使用vector。如果您确实需要使用原始new,则可以使用展示位置新功能。

Square *squares = static_cast<Square*>(operator new(sizeof(*squares) * 10));
for (int i = 0; i < 10; i++) {
  new (static_cast<void*>(squares + i)) Square(i, i);
}

并使用operator delete(squares);删除它。请注意,您需要手动调用这些对象的析构函数。或者,您可以使用原始存储迭代器

创建对象
std::raw_storage_iterator<Square*, Square> rsi(squares);
for (int i = 0; i < 10; i++) {
  *rsi++ = Square(i, i);
}

当然,需要在使用结束时手动调用析构函数。

答案 5 :(得分:1)

我建议您使用std::vector而不是动态分配的数组。 std::vector更容易使用,并且不会泄漏内存。

但是,错误消息引用的缺少的构造函数是Square的构造函数。您需要为Square添加一个不带参数的构造函数。以下 ONE 会:

class Square {
    Square() { ... }
    // Square with dimensions of 0 is empty
    Square(int length=0, int width=0) { ... }
    ...
};

请注意,如果你将这两个文件放在文件中,那么你会收到一个错误,因为当没有给出参数时,无法知道要调用哪个构造函数

即使您使用std::vector,也可能需要默认构造函数。 “可能,”因为你可以绕过它,如果你把自己限制在接受一个对象的std::vector构造函数中,例如:

std::vector<Square> foo(10, Square(0, 0));
// reassign each element accordingly

我已经将此添加为对问题本身的评论。正如Herb Sutter所说,std::vectordesigned to be interchangeable with arrays

  

为什么矢量是连续的如此重要?因为你需要保证向量与C数组的布局兼容,因此我们没有理由不使用向量作为数组的优越且类型安全的替代,即使我们需要使用C代码交换数据。因此,vector是我们通往其他语言和大多数操作系统功能的门户,其通用语言是古老的C数组。

顺便说一句,语法是(假设v是向量)&v[0]。也就是说,取第一个元素的地址(并且它是一个引用,因此除std::vector之外的所有std::vector<bool>都有效),你将得到一个指针,你可以传递给任何函数需要一个指针(当然,您可以将“数组”的长度设为v.size())。

答案 6 :(得分:0)

简单地使用指向指针的指针

Square **squares = new Square*[10];  

它应该有效。但是当你开始使用像vector

这样的STL容器时,我想你真的会更好

答案 7 :(得分:0)

使用std::vector,或使用相同的技术:使用全局new运算符分配“原始”存储空间,并使用placement new在该存储中创建对象(并通过直接调用dtor而不是使用删除。

答案 8 :(得分:0)

Square *squares = new Square[10];

此操作调用默认构造函数 10 次。并且您的代码段中没有一个导致错误。所以,提供一个。只需编写setter方法来初始化类成员。

for (int i = 0; i < 10; i++)
{
     squares[i] = new Square(i, i);
}

new循环中再次进行for操作,您只是泄漏了之前获得的内存,但却按照您的想法行事。

另请不要忘记在delete[]上致电squares