0

I have this snippet of code:

CFoo::CFoo() { InitializeCriticalSection( &m_CriticalSection ); m_IsInitialized = FALSE; m_CBar = CBar(15); } 

When the instance of CBar is constructed on the right hand side of the third line of CFoo's constructor, is the copy constructor invoked to move it to m_CBar, or is only the assignment operator invoked by the compiler?

6
  • 1
    The assignment operator (plus whatever constructor of CBar that's used to construct the temporary on the rhs of the assignment). Commented Jul 1, 2014 at 20:38
  • @T.C., To clarify, the assignment takes care of "constructing" m_CBar in some sense? Do you know of a C++ reference for semantics around these temporary instances? They bit me pretty hard recently and I realized I don't really know what the language is supposed to do around these situations. Commented Jul 1, 2014 at 20:42
  • m_CBar has already been initialized, so you can only have assignment. There's no mystery here. Commented Jul 1, 2014 at 20:44
  • @Daniel Since m_CBar isn't in a member initializer list, it's default-constructed before you enter the constructor body. Commented Jul 1, 2014 at 20:45
  • Better use the constructor initializer list... Saves one ctor, one dtor and one op= call. Commented Jul 1, 2014 at 20:46

3 Answers 3

5

Any class member that's not explicitly initialized in the constructor's member initializer list is default-initialized before the constructor's body is entered. For members of class type, that means default-constructed:

CFoo::CFoo() // : m_CBar() <--------- The constructor behaves as if you wrote this* { InitializeCriticalSection( &m_CriticalSection ); m_IsInitialized = FALSE; m_CBar = CBar(15); } 

Thus, at m_CBar = CBar(15);, you are assigning a temporary instance of CBar, constructed with CBar(15), to m_CBar, which invokes the assignment operator.

It's usually better to construct m_CBar in the member initializer list:

CFoo::CFoo() : m_CBar(15) // Directly constructs m_CBar, passing 15 to the CBar constructor { InitializeCriticalSection( &m_CriticalSection ); m_IsInitialized = FALSE; } 

*: m_CBar() actually value-initializes m_CBar, which does the same thing as default-initialization in cases where, like here, m_CBar is of class type with a user provided constructor. In cases involving scalar types or classes with no user-supplied constructor, value-initialization will cause a zero-initialization (followed by invocation of any nontrivial implicit default constructor for something of non-union class type) to take place, while default-initialization does not cause a zero-initialization. You can find all the fun details with the definitions of all three kinds of initialization (zero, default, and value) in §8.5[dcl.init] of the C++11 standard.

C++14 made some changes to these rules, which plug some holes in certain edge cases. The most important change though is that objects with an explicitly defaulted default constructor are now always treated the same way as objects with an implicitly defined default constructor (and hence always first zero-initialized before the default constructor, if nontrivial, is invoked), regardless of whether it also has other user-provided constructors.

Sign up to request clarification or add additional context in comments.

5 Comments

Not entirely correct. If m_CBar is an aggregate, "the constructor behaves as if..." does not hold.
@juanchopanza if m_CBar is an aggregate then CBar(15) won't work.
@T.C. nitpick - C++11 onwards, this statement isn't true : "// : m_CBar() <--------- The constructor behaves as if you wrote this". m_CBar() is a value initialization. Quoting from here : "Since C++11, value-initializing a class without a user-provided constructor, which has a member of a class type with a user-provided constructor zeroes out the member before calling its constructor."
@Pradhan It is correct in this particular case, since m_CBar is an object of class type with a user-provided constructor. You're not the first person to note this, though, so I'll add a note.
@T.C. agreed. Also, your statement is a good didactic analogy to explain this to someone relatively new to the topic. However, pithy analogies have a tendency to stick, especially when presented unqualified.
1

You will see the constructor CBar(15) called first, and then you will see a call to the assignment operator (demo #1).

Note that if you make the assignment a part of a declaration, like this

CBar a = CBar(15); 

there would very likely be only the constructor - not a constructor + an assignment (demo #2) call when optimization is on, due to copy elision.

3 Comments

Might only be. Not guaranteed, and they are ODR-used in any case.
@Deduplicator There would be no assingment. There could be a copy construction (likely usually elided.)
The second case depends on copy elision and requires the presence of a copy ctor. The compiler is free to construct a temporary, move/copy construct a from the temporary, and then destruct the temporary.
1

Taking your snippet apart:

CFoo::CFoo() { InitializeCriticalSection( &m_CriticalSection ); 

m_CriticalSection was default-initialized (i.e. not initialized, as it's a struct of primitive types without ctor)

 m_IsInitialized = FALSE; 

Dito for m_IsInitialized

 m_CBar = CBar(15); 

m_CBar was default initialized (default-ctor), then the temporary was constructed, then assigned, then the temporary destroyed.

} 

What you should do to reduce work, use the ctor initializer list:

CFoo::CFoo() : m_IsInitialized(), m_CBar(15) { InitializeCriticalSection( &m_CriticalSection ); } 

In C++11 and later you could even put the initializers in the member declaration, and they will be used if not overridden by the ctor init list of the called ctor.

Btw: In a definition with initializer like this:

CBar a = 1; 

Only the respective ctor for a is called.
If it is initialized with a temporary of the same type, the copy can (and will on any compiler worth using) ellided:

Cbar a = CBar(1); 

Or:

CBar a = make_cbar(1,2,3); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.