If a class has only one constructor with one parameter, how to declare an array? I know that vector is recommended in this case. For example, if I have a class
如果一个类只有一个具有一个参数的构造函数,如何声明一个数组?我知道在这种情况下推荐向量。例如,如果我有课
class Foo{
public:
Foo(int i) {}
}
How to declare an array or a vector which contains 10000 Foo objects?
如何声明包含10000个Foo对象的数组或向量?
13 个解决方案
#1
16
For an array you would have to provide an initializer for each element of the array at the point where you define the array.
对于数组,您必须在定义数组的位置为数组的每个元素提供初始化器。
For a vector you can provide an instance to copy for each member of the vector.
对于向量,您可以为向量的每个成员提供一个要复制的实例。
e.g.
如。
std::vector<Foo> thousand_foos(1000, Foo(42));
#2
12
Actually, you can do it as long you use an initialization list, like
实际上,只要使用初始化列表,就可以这样做
Foo foos[4] = { Foo(0),Foo(1),Foo(2),Foo(3) };
however with 10000 objects this is absolutely impractical. I'm not even sure if you were crazy enough to try if the compiler would accept an initialization list this big.
但是对于10000个对象来说,这是完全不切实际的。我甚至不确定如果编译器会接受这么大的初始化列表,是否足够疯狂。
#3
6
sbi had the best answer for plain arrays, but didn't give an example. So...
对于纯数组,sbi有最好的答案,但没有给出示例。所以…
You should use placement new:
你应该使用新位置:
char *place = new char [sizeof(Foo) * 10000];
Foo *fooArray = reinterpret_cast<Foo *>(place);
for (unsigned int i = 0; i < 10000; ++i) {
new (fooArray + i) Foo(i); // Call non-default constructor
}
Keep in mind that when using placement new, you are responsible for calling the objects' destructors -- the compiler won't do it for you:
记住,当你使用新的放置时,你要负责调用对象的析构函数——编译器不会为你这样做:
// In some cleanup code somewhere ...
for (unsigned int i = 0; i < 10000; ++i) {
fooArray[i].~Foo();
}
// Don't forget to delete the "place"
delete [] reinterpret_cast<char *>(fooArray);
This is about the only time you ever see a legitimate explicit call to a destructor.
这是您唯一一次看到对析构函数的合法显式调用。
NOTE: The first version of this had a subtle bug when deleting the "place". It's important to cast the "place" back to the same type that was newed. In other words, fooArray
must be cast back to char *
when deleting it. See the comments below for an explanation.
注意:在删除“位置”时,第一个版本有一个微妙的bug。重要的是要将“地点”转换回新闻的类型。换句话说,在删除char时,必须将fooArray转换回char *。请参阅下面的评论以获得解释。
#4
4
You'd need to do an array of pointers to Foo.
你需要做一个指向Foo的指针数组。
Foo* myArray[10000];
for (int i = 0; i < 10000; ++i)
myArray[i] = new Foo(i);
#5
2
When you declare an object that has no default constructor, you must initialize it in the declaration.
当您声明一个没有默认构造函数的对象时,您必须在声明中初始化它。
Foo a; // not allowed
Foo b(0); // OK
The same goes for arrays of such types:
这种类型的数组也是这样:
Foo c[2]; // not allowed
Foo d[2] = { 0, 1 }; // OK
Foo e[] = { Foo(0), Foo(1), Foo(2) }; // also OK
In your case, you'll probably find it impractical to initialize all 10,000 elements like that, so you might wish to rethink whether the class really shouldn't have a default constructor.
在您的例子中,您可能会发现初始化所有10,000个这样的元素是不切实际的,因此您可能希望重新考虑这个类是否真的不应该有一个默认的构造函数。
#6
1
The only way to define an array of a class with no default constructor would be to initialize it right away - not really an option with 10000 objects.
定义没有默认构造函数的类数组的唯一方法是立即初始化它——而不是使用10000个对象的选项。
You can, however, allocate enough raw memory whichever way you want and use placement new
to create the objects in that memory. But if you want to do this, it's better to use std::vector
which does exactly that:
但是,您可以根据自己的需要分配足够的原始内存,并使用新的放置来在内存中创建对象。但是如果你想这样做,最好使用std::vector它就是这样做的:
#include <iostream>
#include <vector>
struct foo {
foo(int) {}
};
int main()
{
std::vector<foo> v;
v.resize(10000,foo(42));
std::cout << v.size() '\n';
return 0;
}
#7
1
You have to use the aggregate initializer, with 10000 of inidividual initializers between the {}
必须使用聚合初始化器,在{}之间使用10000个独立初始化器
Foo array[10000] = { 1, 2, 3, ..., 10000 };
Of course, specifying 10000 initializers is something from the realm of impossible, but you asked for it yourself. You wanted to declare an array of 10000 objects with no default constructor.
当然,指定10000个初始化器是不可能的事情,但是您自己要求的。您希望声明一个包含10000个对象的数组,其中没有默认构造函数。
#8
1
class single
{
int data;
public:
single()
{
data = 0;
}
single(int i)
{
data = i;
}
};
// in main()
single* obj[10000];
for (unsigned int z = 0; z < 10000; z++)
{
obj[z] = new single(10);
}
#9
0
Another option might be to use an array of boost::optional<Foo>
:
另一个选项可能是使用boost::optional
boost::optional<Foo> foos[10]; // No construction takes place
// (similar to vector::reserve)
foos[i] = Foo(3); // Actual construction
One caveat is that you'll have to access the elements with pointer syntax:
需要注意的一点是,您必须使用指针语法访问元素:
bar(*foos[2]); // "bar" is a function taking a "Foo"
std::cout << foos[3]->baz(); // "baz" is a member of "Foo"
You must also be careful not to access an unitialized element.
您还必须注意不要访问一个统一的元素。
Another caveat is that this not a true replacement for an array of Foo
, as you won't be able to pass it to a function that expects the latter.
另一个需要注意的是,这并不是对一个Foo数组的真正替换,因为您将不能将它传递给一个期望后者的函数。
#10
0
In straight C, using int foo[10000] = {1};
will initialize the first array item to 1
and the remainder of the array to zero. Does C++ not auto-initialize unspecified array members, or does this require a default constructor?
在直线C中,使用int foo[10000] = {1};将把第一个数组项初始化为1,将数组的其余部分初始化为0。c++是否不自动初始化未指定的数组成员,或者这需要一个默认的构造函数?
#11
0
If it makes sense for your class, you could provide a default value for your constructor parameter:
如果对类有意义,可以为构造函数参数提供一个默认值:
class Foo
{
public:
explicit Foo(int i = 0);
}
Now you have a default constructor. (A "default constructor" is a constructor that can be called with no arguments: FAQ)
现在您有了一个默认的构造函数。(“默认构造函数”是可以不带参数地调用的构造函数:FAQ)
I'd also recommend making your constructor explicit, as I did above. It will prevent you from getting Foo
s from int
s when you don't want request them.
我还建议像我上面所做的那样,使您的构造函数显式。它将阻止您在不需要请求时从int获取Foos。
#12
0
Try this.
试试这个。
Foo **ppInstances=0;
size_t total_instances = 10000;
for(int parent=0;parent < total_instances;parent++){
ppInstances[parent]=new Foo( parent );
ppInstances++;
}
for(int parent=0;parent < total_instances;parent++){
delete *ppInstances;
ppInstances--;
}
#13
0
The proper way is use to std::aligned_storage
. You will have to manually construct and destruct items as well as reintrepret_cast
when you want to access an item. I recommend you write a small wrapper class around storage_t
to take care of this. Someone mentioned using boost::optional
which uses a bool and a storage_t under the hood. This method saves you a bool.
正确的方法是使用std::align ned_storage。当您想要访问一个项目时,您必须手动构造和销毁项以及reintrepret_cast。我建议您在storage_t周围编写一个小包装类来处理这个问题。有人提到使用boost:::optional,使用bool和storage_t。这个方法省了你一大笔钱。
template<typename T>
using storage_t = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
struct Foo;
size_t i = 55;
storage_t<Foo> items[1000]; // array of suitable storage for 1000 T's
new (reintrepret_cast<Foo*>(items + i)) Foo(42); // construct new Foo using placement new
*reintrepret_cast<Foo*>(items + i) = Foo(27); // assign Foo
reintrepret_cast<Foo*>(items + i)->~Foo() // call destructor
#1
16
For an array you would have to provide an initializer for each element of the array at the point where you define the array.
对于数组,您必须在定义数组的位置为数组的每个元素提供初始化器。
For a vector you can provide an instance to copy for each member of the vector.
对于向量,您可以为向量的每个成员提供一个要复制的实例。
e.g.
如。
std::vector<Foo> thousand_foos(1000, Foo(42));
#2
12
Actually, you can do it as long you use an initialization list, like
实际上,只要使用初始化列表,就可以这样做
Foo foos[4] = { Foo(0),Foo(1),Foo(2),Foo(3) };
however with 10000 objects this is absolutely impractical. I'm not even sure if you were crazy enough to try if the compiler would accept an initialization list this big.
但是对于10000个对象来说,这是完全不切实际的。我甚至不确定如果编译器会接受这么大的初始化列表,是否足够疯狂。
#3
6
sbi had the best answer for plain arrays, but didn't give an example. So...
对于纯数组,sbi有最好的答案,但没有给出示例。所以…
You should use placement new:
你应该使用新位置:
char *place = new char [sizeof(Foo) * 10000];
Foo *fooArray = reinterpret_cast<Foo *>(place);
for (unsigned int i = 0; i < 10000; ++i) {
new (fooArray + i) Foo(i); // Call non-default constructor
}
Keep in mind that when using placement new, you are responsible for calling the objects' destructors -- the compiler won't do it for you:
记住,当你使用新的放置时,你要负责调用对象的析构函数——编译器不会为你这样做:
// In some cleanup code somewhere ...
for (unsigned int i = 0; i < 10000; ++i) {
fooArray[i].~Foo();
}
// Don't forget to delete the "place"
delete [] reinterpret_cast<char *>(fooArray);
This is about the only time you ever see a legitimate explicit call to a destructor.
这是您唯一一次看到对析构函数的合法显式调用。
NOTE: The first version of this had a subtle bug when deleting the "place". It's important to cast the "place" back to the same type that was newed. In other words, fooArray
must be cast back to char *
when deleting it. See the comments below for an explanation.
注意:在删除“位置”时,第一个版本有一个微妙的bug。重要的是要将“地点”转换回新闻的类型。换句话说,在删除char时,必须将fooArray转换回char *。请参阅下面的评论以获得解释。
#4
4
You'd need to do an array of pointers to Foo.
你需要做一个指向Foo的指针数组。
Foo* myArray[10000];
for (int i = 0; i < 10000; ++i)
myArray[i] = new Foo(i);
#5
2
When you declare an object that has no default constructor, you must initialize it in the declaration.
当您声明一个没有默认构造函数的对象时,您必须在声明中初始化它。
Foo a; // not allowed
Foo b(0); // OK
The same goes for arrays of such types:
这种类型的数组也是这样:
Foo c[2]; // not allowed
Foo d[2] = { 0, 1 }; // OK
Foo e[] = { Foo(0), Foo(1), Foo(2) }; // also OK
In your case, you'll probably find it impractical to initialize all 10,000 elements like that, so you might wish to rethink whether the class really shouldn't have a default constructor.
在您的例子中,您可能会发现初始化所有10,000个这样的元素是不切实际的,因此您可能希望重新考虑这个类是否真的不应该有一个默认的构造函数。
#6
1
The only way to define an array of a class with no default constructor would be to initialize it right away - not really an option with 10000 objects.
定义没有默认构造函数的类数组的唯一方法是立即初始化它——而不是使用10000个对象的选项。
You can, however, allocate enough raw memory whichever way you want and use placement new
to create the objects in that memory. But if you want to do this, it's better to use std::vector
which does exactly that:
但是,您可以根据自己的需要分配足够的原始内存,并使用新的放置来在内存中创建对象。但是如果你想这样做,最好使用std::vector它就是这样做的:
#include <iostream>
#include <vector>
struct foo {
foo(int) {}
};
int main()
{
std::vector<foo> v;
v.resize(10000,foo(42));
std::cout << v.size() '\n';
return 0;
}
#7
1
You have to use the aggregate initializer, with 10000 of inidividual initializers between the {}
必须使用聚合初始化器,在{}之间使用10000个独立初始化器
Foo array[10000] = { 1, 2, 3, ..., 10000 };
Of course, specifying 10000 initializers is something from the realm of impossible, but you asked for it yourself. You wanted to declare an array of 10000 objects with no default constructor.
当然,指定10000个初始化器是不可能的事情,但是您自己要求的。您希望声明一个包含10000个对象的数组,其中没有默认构造函数。
#8
1
class single
{
int data;
public:
single()
{
data = 0;
}
single(int i)
{
data = i;
}
};
// in main()
single* obj[10000];
for (unsigned int z = 0; z < 10000; z++)
{
obj[z] = new single(10);
}
#9
0
Another option might be to use an array of boost::optional<Foo>
:
另一个选项可能是使用boost::optional
boost::optional<Foo> foos[10]; // No construction takes place
// (similar to vector::reserve)
foos[i] = Foo(3); // Actual construction
One caveat is that you'll have to access the elements with pointer syntax:
需要注意的一点是,您必须使用指针语法访问元素:
bar(*foos[2]); // "bar" is a function taking a "Foo"
std::cout << foos[3]->baz(); // "baz" is a member of "Foo"
You must also be careful not to access an unitialized element.
您还必须注意不要访问一个统一的元素。
Another caveat is that this not a true replacement for an array of Foo
, as you won't be able to pass it to a function that expects the latter.
另一个需要注意的是,这并不是对一个Foo数组的真正替换,因为您将不能将它传递给一个期望后者的函数。
#10
0
In straight C, using int foo[10000] = {1};
will initialize the first array item to 1
and the remainder of the array to zero. Does C++ not auto-initialize unspecified array members, or does this require a default constructor?
在直线C中,使用int foo[10000] = {1};将把第一个数组项初始化为1,将数组的其余部分初始化为0。c++是否不自动初始化未指定的数组成员,或者这需要一个默认的构造函数?
#11
0
If it makes sense for your class, you could provide a default value for your constructor parameter:
如果对类有意义,可以为构造函数参数提供一个默认值:
class Foo
{
public:
explicit Foo(int i = 0);
}
Now you have a default constructor. (A "default constructor" is a constructor that can be called with no arguments: FAQ)
现在您有了一个默认的构造函数。(“默认构造函数”是可以不带参数地调用的构造函数:FAQ)
I'd also recommend making your constructor explicit, as I did above. It will prevent you from getting Foo
s from int
s when you don't want request them.
我还建议像我上面所做的那样,使您的构造函数显式。它将阻止您在不需要请求时从int获取Foos。
#12
0
Try this.
试试这个。
Foo **ppInstances=0;
size_t total_instances = 10000;
for(int parent=0;parent < total_instances;parent++){
ppInstances[parent]=new Foo( parent );
ppInstances++;
}
for(int parent=0;parent < total_instances;parent++){
delete *ppInstances;
ppInstances--;
}
#13
0
The proper way is use to std::aligned_storage
. You will have to manually construct and destruct items as well as reintrepret_cast
when you want to access an item. I recommend you write a small wrapper class around storage_t
to take care of this. Someone mentioned using boost::optional
which uses a bool and a storage_t under the hood. This method saves you a bool.
正确的方法是使用std::align ned_storage。当您想要访问一个项目时,您必须手动构造和销毁项以及reintrepret_cast。我建议您在storage_t周围编写一个小包装类来处理这个问题。有人提到使用boost:::optional,使用bool和storage_t。这个方法省了你一大笔钱。
template<typename T>
using storage_t = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
struct Foo;
size_t i = 55;
storage_t<Foo> items[1000]; // array of suitable storage for 1000 T's
new (reintrepret_cast<Foo*>(items + i)) Foo(42); // construct new Foo using placement new
*reintrepret_cast<Foo*>(items + i) = Foo(27); // assign Foo
reintrepret_cast<Foo*>(items + i)->~Foo() // call destructor