Reputation: 3164
We know that a built-in array can neither be copied nor be assigned. So If it is a member data of a class/struct/union It is OK to leave the compiler do its magic to copy them:
struct ArrInt5{
ArrInt5() = default;
ArrInt5(ArrInt5 const&) = default; // OK
int a[5];
};
ArrInt5 a, b = a; // OK
Sometimes that is not the case for example if the array holds objects of non-default- constructible objects. in that case we do need to define our copy-ctor to do the job:
struct Bar{
// deleted default ctor
Bar(int x) : x_(x){}
int x_ = 0;
};
struct Foo{
Foo();
Foo(Foo const&);
Bar arr_[5];
};
Foo::Foo() : arr_{0, 1, 2, 3, 4}
{}
Foo::Foo(Foo const& rhs) : arr_{rhs.arr_[0], rhs.arr_[1], rhs.arr_[2], rhs.arr_[3], rhs.arr_[4]}
{}
As you can see Foo
has a built-in array of five objects of type struct Bar
that type is not default-constructible so the default ctor and the copy ctor must initialize it (arr_
).
The problem is: How could initialize that array if it is of a big size lets say 1 million element? Should I hard copy them element by element? or there's some workaround?
std::array
but I'm not on that topic, I'm asking whether there's a workaround for my built-in array of non default-constructible objects.Upvotes: 0
Views: 1301
Reputation: 11220
The only way to generate this effect for you automatically is to wrap your array in a class type of some kind that has a compiler-generated copy constructor (e.g. such as a default
ed constructor). In your particular example, you could just have Foo(const Foo&)
be default
ed:
struct Foo{
Foo();
Foo(Foo const&) = default;
// This generates your:
// "Foo::Foo(Foo const& rhs) : arr_{rhs.arr_[0], rhs.arr_[1], rhs.arr_[2], rhs.arr_[3], rhs.arr_[4]}"
// by the compiler
Bar arr_[5];
};
However the above only works if your copy-logic is trivial. For more complex copying, you can't always have a default
copy constructor -- but we can solve this more generally.
If you wrap an array data member of any type/size in a struct
or class
and make sure it has compiler-generated copy constructors, then copying is easy in a constructor.
For example:
template <typename T, std::size_t N>
struct Array {
...
T data[N];
};
This allows for the simple case of copying:
Array<Bar,1000000> a = {{...}};
Array<Bar,1000000> b = a;
Or the more complex case of copying in a constructor that might require more logic than the compiler-generated ones:
class Foo {
...
Foo(const Foo& other);
...
Array<Bar,100000> arr_;
};
Foo::Foo(const Foo& other)
: arr_{other.arr_}
{
... other complex copy logic ...
}
At which point, congratulations -- you have invented std::array
!
std::array
was added to the standard library exactly because it was this simple to introduce a library-solution to this problem without having to alter the language itself. Don't shy away from it.
Upvotes: 5