1

假设我有一个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 数组,然后再进行构造

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

4

9 回答 9

7

使用vector. 只要Square是可复制的就没有这个问题。

vector<Square> squares;
for (int i = 0; i < 10; i++)
{
     squares.push_back(Square(i, i));
}
于 2011-03-30T16:47:04.737 回答
5

你可以创建一个指针数组Square

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

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

正如其他人指出的那样,考虑使用它是一个好主意std::vector

于 2011-03-30T16:45:41.240 回答
1

您应该创建一个指向SQuare.

但是,我也建议使用 astd::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

于 2011-03-30T16:47:44.220 回答
1

标准库容器执行此操作的方式是放置 new。仅使用标准库容器,例如std::vector,绝对是最简单的方法。新的安置是最难的。分配单个对象并将指针保存在数组中,就像 Xeo 提到的那样,落在中间。

于 2011-03-30T16:48:52.600 回答
1

在适用的程序中使用vector。如果你真的需要使用 raw new,你可以使用placement 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);
}

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

于 2011-03-30T16:51:07.413 回答
1

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

但是,错误消息所指的缺失构造函数是Square的构造函数。您需要添加一个Square不带参数的构造函数。 以下其中一项将执行:

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::vector旨在与数组互换

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

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

于 2011-03-30T16:52:59.023 回答
0

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

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

它应该工作。但我想当你开始使用像 vector 这样的 STL 容器时,你会过得更好

于 2011-03-30T16:49:06.743 回答
0

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

于 2011-03-30T16:49:11.523 回答
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

于 2011-03-30T16:51:54.403 回答