7

In this code fragment, which constructor is actually called?

Vector v = getVector(); 

Vector has copy constructor, default constructor and assignment operator:

class Vector {
public:
    ...
    Vector();
    Vector(const Vector& other);
    Vector& operator=(const Vector& other);
};

getVector returns by value.

Vector getVector();

Code uses C++03 standard.

Code fragment looks like it is supposed to call default constructor and then assignment operator, but I suspect that this declaration is another form of using copy constructor. Which is correct?

Rafał Rawicki
  • 22,324
  • 5
  • 59
  • 79
SigTerm
  • 26,089
  • 6
  • 66
  • 115

4 Answers4

8

When = appears in an initialization, it calls the copy constructor. The general form is not exactly the same as calling the copy constructor directly though. In the statement T a = expr;, what happens is that if expr is of type T, the copy constructor is called. If expr is not of type T, then first an implicit conversion is done, if possible, then the copy constructor is called with that as an argument. If an implicit conversion is not possible, then the code is ill-formed.

Depending upon how getVector() is structured, the copy may be optimized away, and the object that was created inside the function is the same physical object that gets stored in v.

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • One rule worth nothing is that the copy constructor must be accessible (e.g. public) even if indeed the copy construction itself ends up being eliminated. So may be making the copy constructor private the code will not compile and making it public it will compile but the copy constructor will not be called. – 6502 Mar 31 '12 at 16:22
  • "the same physical object that gets stored in v" - rather, the object created inside the function is the same physical object as `v`. I'd normally say either `v` is the name of an object, or `v` is that object, but not "an object is stored in `v`". The usual implementation of this copy elision is that the caller of `getVector` passes a pointer as an additional hidden parameter, and `getVector` constructs its return value at that address. In this case, the standard permits the calling code to pass `&v` as that hidden parameter. – Steve Jessop Mar 31 '12 at 17:47
2

Assuming that you haven't done something pathological outside of the code you are showing, your declaration is a copy-initialization, and the second part of this rule applies:

13.3.1.3 Initialization by constructor [over.match.ctor]

1 When objects of class type are direct-initialized (8.5), or copy-initialized from an 
  expression of the same or a derived class type (8.5), overload resolution selects the
  constructor. For direct-initialization, the candidate functions are all the constructors
  of the class of the object being initialized. For copy-initialization, the candidate 
  functions are all the converting constructors (12.3.1) of that class. The argument 
  list is the expression-list within the parentheses of the initializer.

For a simple test case, see Eli Bendersky's post, here: http://eli.thegreenplace.net/2003/07/23/variable-initialization-in-c/

Austin Hastings
  • 617
  • 4
  • 13
1

Always remember the rule:
Whenever, an object is being created and given some value in the same single statement then it is never an assignment.

To add Further,

Case 1:

Vector v1;
Vector v(v1);

Case 2:

   Vector v = getVector(); 

In the above two formats Case 1 is Direct Initialization while Case 2 is known as Copy Initialization.

How does Copy Initialization work?
Copy initialization constructs an implicit conversion sequence: It tries to convert return value of getVector() to an object of type Vector. It can then copy the created object into the object being initialized, So it needs a accessible copy constructor.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
0

The copy constructor actually gets elided in this case (check this) and just the default constructor ends up getting called

EDIT:

The constructor is only sometimes elided, as per Benjamin's answer. For some reason I read that as you calling the constructor directly.

Community
  • 1
  • 1
SirGuy
  • 10,660
  • 2
  • 36
  • 66