c++ 中的空动态数组

发布于 2024-10-27 12:43:59 字数 397 浏览 1 评论 0原文

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

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

但是这失败了,说没有可用的适当的默认构造函数。那么我如何创建一个空数组或 NULL 数组,然后稍后进行构造?

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

Let's say I have an object called Square with the constructor Square(int rx, int ry), i want to create a dynamic array of Squares, with different arguments in the constructor:

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

However this fails, saying no appropriate default constructor available. So how do i create an empty or NULL array and then do constructions later?

EDIT: This has to be an array, due to other things in code, to hard to explain here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

青春如此纠结 2024-11-03 12:43:59

使用向量。只要 Square 是可复制的,就不存在这个问题。

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

Use vector. It doesn't have this problem as long as Square is copyable.

vector<Square> squares;
for (int i = 0; i < 10; i++)
{
     squares.push_back(Square(i, i));
}
爱她像谁 2024-11-03 12:43:59

您可以创建一个指向 Square指针数组:

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

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

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

You could make an array of pointers to Square:

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

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

As others have pointed out, it is a good idea to consider using std::vector instead.

风吹雪碎 2024-11-03 12:43:59

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

The way the standard library containers do it is with placement new. Just using a standard library container, like std::vector, is definitely the easiest way. And placement new is the hardest. Allocating individual objects and keeping pointers in the array, like Xeo mentioned, falls in the middle.

溇涏 2024-11-03 12:43:59

您应该创建一个指向 SQuare 的指针数组。

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

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

这会给出类似的内容:

#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指针容器库

You should make an array of pointers to SQuare.

However, I would also recommend to use a std::vector instead of a "classic" array, this is a good solution if Square is copyable.

However, if it is not, or if you still decide to go the pointer way, make it a std::vector of shared_ptr to leave all the deletion burden to the compiler.

This would give something like:

#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));
}

To go even further, you could take a look at the Boost Pointer Container library.

凌乱心跳 2024-11-03 12:43:59

如果适用,请在程序中使用向量。如果您确实需要使用原始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);
}

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

Use vector in programs where applicable. If you really need to use a raw new, you can use 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);
}

And delete it with operator delete(squares);. Notice that you need to manually call the destructors of these objects then. Alternatively, you can create the objects with a raw storage iterator

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

The need to manually call the destructors at the end of use stays, of course.

夏末染殇 2024-11-03 12:43:59

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

但是,错误消息所指的缺少的构造函数是 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 代码交换数据,我们也没有理由不使用向量作为数组的高级且类型安全的替代方案。因此,向量是我们通向其他语言和大多数操作系统功能的门户,其通用语言是古老的 C 数组。

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

I would recommend you use a std::vector instead of a dynamically-allocated array. std::vectors are much easier to work with, and don't leak memory.

However, the missing constructor the error message refers to is Square's constructor. You need to add a constructor for Square that takes no arguments. ONE of the following will do:

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

Please note that if you put both of these in the file, then you will get an error, because it will be impossible to know which constructor to call when no arguments are given.

You'll probably want the default constructor even if you use a std::vector. "Probably," because you can get around it, if you limit yourself to std::vector's constructors that take an object, eg.:

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

I've already added this as a comment to the question itself. As Herb Sutter says, std::vector is designed to be interchangeable with arrays:

Why is it so important that vectors be contiguous? Because that’s what you need to guarantee that a vector is layout-compatible with a C array, and therefore we have no reason not to use vector as a superior and type-safe alternative to arrays even when we need to exchange data with C code. So vector is our gateway to other languages and most operating systems features, whose lingua franca is the venerable C array.

The syntax, by the way is (assuming v is a vector) &v[0]. That is, take the address of the first element (and it's a reference, so that works on all std::vectors except for std::vector<bool>) and you'll get a pointer that you can pass to any function that expects a pointer (you can, of course, get the length of the "array" as v.size()).

寂寞陪衬 2024-11-03 12:43:59

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

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

,它应该可以工作。但我想当你开始使用像矢量这样的 STL 容器时,你的情况真的会更好

Simple use a pointer to a pointer

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

And it should work. But I guess you are really better off when you start using STL containers like vector

長街聽風 2024-11-03 12:43:59

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

Use std::vector, or use the same technique it does: allocate "raw" storage space with the global new operator, and create objects in that storage using placement new (and destroy them by invoking the dtor directly instead of using delete.

淡莣 2024-11-03 12:43:59
Square *squares = new Square[10];

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

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

通过在 for 循环中再次进行 new 操作,您只是泄漏了之前获取的内存,但做了您所想的事情。

另外,不要忘记在 squares 上调用 delete[]

Square *squares = new Square[10];

This operation calls the default constructor 10 times. And there is not one in your snippet resulting error. So, provide one. Just write setter method to initialize class members.

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

By new operation again in the for loop, you are just leaking the memory acquired before but does what you think.

Also don't forget to call delete[] on squares.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文