|
||||
|
Section 10:
|
[10.5] Which constructor gets called when I create an array of Fred objects?
Fred's default constructor (except as discussed below).
class Fred {
public:
Fred();
...
};
int main()
{
Fred a[10]; ← calls the default constructor 10 times
Fred* p = new Fred[10]; ← calls the default constructor 10 times
...
}
If your class doesn't have a default constructor,
you'll get a compile-time error when you attempt to create an array using the
above simple syntax:
class Fred {
public:
Fred(int i, int j); ← assume there is no default constructor
...
};
int main()
{
Fred a[10]; ← ERROR: Fred doesn't have a default constructor
Fred* p = new Fred[10]; ← ERROR: Fred doesn't have a default constructor
...
}
However, even if your class already has a default constructor, you should try
to use std::vector<Fred> rather than an
array (arrays are evil). std::vector
lets you decide to use any constructor, not just the default constructor:
#include <vector>
int main()
{
std::vector<Fred> a(10, Fred(5,7)); ← the 10 Fred objects in std::vector a will be initialized with Fred(5,7)
...
}
Even though you ought to use a std::vector rather than an
array, there are times when an array might be the right thing to do, and for
those, you might need the "explicit initialization of arrays" syntax. Here's
how:
class Fred {
public:
Fred(int i, int j); ← assume there is no default constructor
...
};
int main()
{
Fred a[10] = {
Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7), // The 10 Fred objects are
Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7) // initialized using Fred(5,7)
};
...
}
Of course you don't have to do Fred(5,7) for every entry — you can
put in any numbers you want, even parameters or other variables.
Finally, you can use placement-new to manually initialize the elements of the array. Warning: it's ugly: the raw array can't be of type Fred, so you'll need a bunch of pointer-casts to do things like compute array index operations. Warning: it's compiler- and hardware-dependent: you'll need to make sure the storage is aligned with an alignment that is at least as strict as is required for objects of class Fred. Warning: it's tedious to make it exception-safe: you'll need to manually destruct the elements, including in the case when an exception is thrown part-way through the loop that calls the constructors. But if you really want to do it anyway, read up on placement-new. (BTW placement-new is the magic that is used inside of std::vector. The complexity of getting everything right is yet another reason to use std::vector.) By the way, did I ever mention that arrays are evil? Or did I mention that you ought to use a std::vector unless there is a compelling reason to use an array? |
|||