Initialization of single-constructor class objects

D

Dave Theese

Hello all,

Consider a class foo that has a public, non-explicit constructor that can be
called with one argument (either there's only one parameter or the second
and subsequent parameters all have default values). For the sake of making
the discussion concrete, let's say that argument is of type int. There are
two syntaxes to define an object of this class:

foo var(5);
foo var = 5;

Is there *any* semantic difference at all (no matter how small) between
these two forms?

Thanks,
Dave
 
R

Russell Hanneken

Dave Theese said:
foo var(5);
foo var = 5;

Is there *any* semantic difference at all (no matter how small) between
these two forms?

Yes. The first version is "direct initialization," the second is "copy
initialization." The first version creates a foo by calling the constructor
that takes one int. The second version creates a temporary foo by calling
the constructor that takes one int, and then creats var by passing the
temporary foo to the foo copy constructor.

Okay, maybe not. The C++ standard actually allows compilers to make the
second version do the same thing as the first version. But there's no
guarantee.

Here's a good discussion:

http://www.semantics.org/gotchas/gotcha34.pdf

Regards,

Russell Hanneken
(e-mail address removed)
 
D

Dave Theese

Ahhh, OK. My thoughts were exactly along the lines that perhaps a temporary
would be constructed; that's why I asked the question. In the case I tried,
I declared a copy constructor private and did not define it to prevent this.
Everything still compiled and ran fine. But I wasn't sure if that behavior
could be counted on. It sounds as if it cannot.

Along a similar vein, I've noticed that when I return an object from a
function (by value, not by reference), there is no temporary constructed.
Of course, there will be in the general case and this cannot be counted on
either. I suppose these cases where temporaries would normally be expected
but do not appear are compiler optimizations.

Thanks man!
 
R

Russell Hanneken

Dave Theese said:
Along a similar vein, I've noticed that when I return an object from a
function (by value, not by reference), there is no temporary constructed.

Yes, the C++ standard explicitly allows the compiler to not make a temporary
in that case.
I suppose these cases where temporaries would normally be expected
but do not appear are compiler optimizations.

The word "optimizations" might be misleading; the "optimized" code in this
case could behave differently from the "unoptimized" code. The copy
constructor might have side effects that never happen because the copy
constructor doesn't get called.

Here's the relevant passage from the standard:

Whenever a temporary class object is copied using a copy
constructor, and this object and the copy have the same cv-
unqualified type, an implementation is permitted to treat the
original and the copy as two different ways of referring to the
same object and not perform a copy at all, even if the class copy
constructor or destructor have side effects. For a function with
a class return type, if the expression in the return statement is
the name of a local object, and the cv-unqualified type of the
local object is the same as the function return type, an
implementation is permitted to omit creating the temporary object
to hold the function return value, even if the class copy
constructor or destructor has side effects. In these cases, the
object is destroyed at the later of times when the original and
the copy would have been destroyed without the
optimization (section 12.8, paragraph 15).

Regards,

Russell Hanneken
(e-mail address removed)
 
J

Josh Sebastian

That a constructor takes an integer argument does not mean that integers
can be assigned to the object constructed:

class A {

double* k;

A(int d) : k(new double[d]) { }

};


Now the statement

A x(5);

makes sense and allocate A::k as an array of five doubles. But the
assignement

A x=5;

makes no sense.

It's not assignment. It uses the equal sign, but in this case, it's not
the assignment operator. It's copy initialization, just like Russell said.

You're right that it doesn't make much sense (from a human's point of
view) in this circumstance, but it's still legal. In such a situation, you
probably want to make the constructor `explicit'.

Josh
 
M

mjm

Suppose in my example we don't define operator =.
Then what happens if the statement

A x=5;

is executed?
 
S

Sam Holden

Suppose in my example we don't define operator =.
Then what happens if the statement

A x=5;

is executed?

A constructor of A gets called. If no matching constructor exists then it
doesn't get executed since it doesn't compile.
 
J

John Harrison

mjm said:
Suppose in my example we don't define operator =.
Then what happens if the statement

A x=5;

is executed?

Russell Hanneken has already explained this in this thread

A x=5;

is more or less equivalent to

A x(A(5));

The point is that the '=' sign does not mean assignment in this context. In
fact it couldn't mean assignment since assignment only happens when an
object has already been constructed. In this case you are constructing x.

john
 
M

mjm

Thanks,

This is interesting and counter intuitive.
I was aware of how it in the case of

A x=y;

where y is of type A.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top