Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Constructor call in array definition

0 views
Skip to first unread message

Christian Meier

unread,
Feb 4, 2010, 7:38:47 AM2/4/10
to
Hello NG

Is it the standard behaviour that the copy constructor is called when I
initialize an array of a class type?
And if so, is it possible to initialize an array of objects without invoking
the copy constructor?

My problem is that my class has a private copy constructor (and an explicit
constructor - but I do not know whether this is relevant).
Below is my sample code (which does not compile). How do I have to write the
definition of "D::c" so that it compiles without changing class C?

Thanks in advance!

Greets Chris

-----------------

class C
{
public:
explicit C(int i) : i_(i) {}
private:
C(const C&);
int i_;
};

class D
{
static C c[2];
};


C D::c[2] = { C(0), C(1) };


int main()
{
}


Victor Bazarov

unread,
Feb 4, 2010, 8:23:27 AM2/4/10
to
Christian Meier wrote:
> Is it the standard behaviour that the copy constructor is called when I
> initialize an array of a class type?

Yes, you're initializing your objects from temporaries. That requires a
callable copy c-tor.

> And if so, is it possible to initialize an array of objects without invoking
> the copy constructor?

Don't create temporaries. You could initialise those elements directly,
but not with an explicit c-tor.

> My problem is that my class has a private copy constructor (and an explicit
> constructor - but I do not know whether this is relevant).
> Below is my sample code (which does not compile). How do I have to write the
> definition of "D::c" so that it compiles without changing class C?

There is no way.

At first I was thinking you could leave it uninitialised, but that would
require a default c-tor, which you don't have. Adding it would mean
changing class C.

So, something's gotta give.

>
> Thanks in advance!
>
> Greets Chris
>
> -----------------
>
> class C
> {
> public:
> explicit C(int i) : i_(i) {}
> private:
> C(const C&);
> int i_;
> };
>
> class D
> {
> static C c[2];
> };
>
>
> C D::c[2] = { C(0), C(1) };
>
>
> int main()
> {
> }
>
>

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

Christian Meier

unread,
Feb 4, 2010, 8:53:47 AM2/4/10
to
Thanks for your answer.

Victor Bazarov wrote:
> Christian Meier wrote:
>> Is it the standard behaviour that the copy constructor is called when I
>> initialize an array of a class type?
>
> Yes, you're initializing your objects from temporaries. That requires a
> callable copy c-tor.
>
>> And if so, is it possible to initialize an array of objects without
>> invoking the copy constructor?
>
> Don't create temporaries. You could initialise those elements directly,
> but not with an explicit c-tor.
>

How do I do that? If I remove the "exclicit" keyword in my sample code and
change the initializer-statement to "C D::c[2] = { 0, 1 };" then my compiler
still tries to call the copy constructor:
main.cpp:6: error: 'C::C(const C&)' is private

>> My problem is that my class has a private copy constructor (and an
>> explicit constructor - but I do not know whether this is relevant).
>> Below is my sample code (which does not compile). How do I have to write
>> the definition of "D::c" so that it compiles without changing class C?
>
> There is no way.
>
> At first I was thinking you could leave it uninitialised, but that would
> require a default c-tor, which you don't have. Adding it would mean
> changing class C.
>
> So, something's gotta give.
>

If I left it uninitialized then they would have the same value.

Victor Bazarov

unread,
Feb 4, 2010, 11:18:19 AM2/4/10
to
Christian Meier wrote:
> Thanks for your answer.
>
> Victor Bazarov wrote:
>> Christian Meier wrote:
>>> Is it the standard behaviour that the copy constructor is called when I
>>> initialize an array of a class type?
>> Yes, you're initializing your objects from temporaries. That requires a
>> callable copy c-tor.
>>
>>> And if so, is it possible to initialize an array of objects without
>>> invoking the copy constructor?
>> Don't create temporaries. You could initialise those elements directly,
>> but not with an explicit c-tor.
>>
>
> How do I do that? If I remove the "exclicit" keyword in my sample code and
> change the initializer-statement to "C D::c[2] = { 0, 1 };" then my compiler
> still tries to call the copy constructor:
> main.cpp:6: error: 'C::C(const C&)' is private

Hm... Maybe I'm wrong. I thought it would do direct initialization.
Lemme look it up... <opens the Standard>

8.5/12 says <<The initialization that occurs in argument passing,
function return, throwing an exception (15.1), handling
an exception (15.3), and brace-enclosed initializer lists (8.5.1) is
called copy-initialization ...>>

That's too bad (for your situation, I mean). I was wrong - the copy
c-tor still needs to be accessible even if the compiler doesn't need it.
It's the "as-if" rule.

>>> My problem is that my class has a private copy constructor (and an
>>> explicit constructor - but I do not know whether this is relevant).
>>> Below is my sample code (which does not compile). How do I have to write
>>> the definition of "D::c" so that it compiles without changing class C?
>> There is no way.
>>
>> At first I was thinking you could leave it uninitialised, but that would
>> require a default c-tor, which you don't have. Adding it would mean
>> changing class C.
>>
>> So, something's gotta give.
>>
>
> If I left it uninitialized then they would have the same value.

They can't be left uninitialised, your class has no default c-tor.

Robert Fendt

unread,
Feb 4, 2010, 1:56:04 PM2/4/10
to
And thus spake Victor Bazarov <v.Aba...@comAcast.net>
Thu, 04 Feb 2010 11:18:19 -0500:

> >> So, something's gotta give.
> >>
> >
> > If I left it uninitialized then they would have the same value.
>
> They can't be left uninitialised, your class has no default c-tor.

If you do not want to lose the access level protection, you can only use a factory function: either a friend or a class member has to create the array and return a pointer to it. There is no other way (at least to my knowledge), due to the array initialisation limitations in C++.

Regards,
Robert

James Kanze

unread,
Feb 4, 2010, 5:31:14 PM2/4/10
to
On Feb 4, 1:23 pm, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
> Christian Meier wrote:
> > Is it the standard behaviour that the copy constructor is
> > called when I initialize an array of a class type?

> Yes, you're initializing your objects from temporaries. That
> requires a callable copy c-tor.

> > And if so, is it possible to initialize an array of objects
> > without invoking the copy constructor?

> Don't create temporaries. You could initialise those elements
> directly, but not with an explicit c-tor.

> > My problem is that my class has a private copy constructor
> > (and an explicit constructor - but I do not know whether
> > this is relevant). Below is my sample code (which does not
> > compile). How do I have to write the definition of "D::c" so
> > that it compiles without changing class C?

> There is no way.

There is a way, but it's far from simple. The "array" must be
declared as an array of unsigned char, with the appropriate
size, and the appropriate precautions to ensure correct
alignment, and then you use placement new to initialize each
object in the array.

Not for the faint at heart.

--
James Kanze

Christian Meier

unread,
Feb 5, 2010, 1:18:01 AM2/5/10
to
Victor Bazarov wrote:

<snip>

> 8.5/12 says <<The initialization that occurs in argument passing, function
> return, throwing an exception (15.1), handling
> an exception (15.3), and brace-enclosed initializer lists (8.5.1) is
> called copy-initialization ...>>
>
> That's too bad (for your situation, I mean). I was wrong - the copy c-tor
> still needs to be accessible even if the compiler doesn't need it. It's
> the "as-if" rule.

You're right, 8.5 / 12 is the explanation. Not only the "is called
copy-initialization" but also that "is equivalent to the form T x = a;".
It explains why I have to create temporaries when having an explicit
constructor (and an accessible copy constructor).

Thanks for your answers.

Greets Chris


0 new messages