Constructor or Assignment Operator

限于喜欢 提交于 2019-12-05 00:17:42


Can you help me is there definition in C++ standard that describes which one will be called constructor or assignment operator in this case:

#include <iostream>

using namespace std;

class CTest

 CTest() : m_nTest(0)
  cout << "Default constructor" << endl;

 CTest(int a) : m_nTest(a)
  cout << "Int constructor" << endl;

 CTest(const CTest& obj)
  m_nTest = obj.m_nTest;
  cout << "Copy constructor" << endl;

 CTest& operator=(int rhs)
  m_nTest = rhs;
  cout << "Assignment" << endl;
  return *this;

 int m_nTest;

int _tmain(int argc, _TCHAR* argv[])
 CTest b = 5;

 return 0;

Or is it just a matter of compiler optimization?


What is happening here depends a bit on your compiler. It could create a temporary object using the int constructor and then copy construct b from that temporary. It will most likely elide the copy constructor call however. In neither case will the assignment operator be used.


It’s always the default constructor taking an int that’s called in this case. This is called an implicit conversion and is semantically equivalent to the following code:

CTest b(5);

The assignment operator is never invoked in an initialization. Consider the following case:

CTest b = CTest(5);

Here, we call the constructor (taking an int) explicitly and then assign the result to b. But once again, no assignment operator is ever called. Strictly speaking, both cases would call the copy constructor after creating an object of type CTest. But in fact, the standard actively encourages compilers to optimize the copy constructor call here (§12.8/15) – in practice, modern C++ compilers won’t emit a copycon call here.


CTest b = 5; is an exact equivalent of CTest b(CTest(5)); Two constructors are involved: one taking an int (implicitly converting from integer 5), and the copy constructor. The assignment operator is in no way involved here.

The compiler may well optimize out the unnecessary copy, so the result would be as if you had typed CTest b(5). Therefore at runtime, both seeing "Copy constructor" printed (GCC with the -fno-elide-constructors option) or not (GCC by default) would be valid output of the program.

However, conceptually the compiler is required to check if an accessible and suitable copy constructor exists. The form CTest b = 5; would fail to compile if a) the copy constructor is private/protected (not accessible) or b) the copy constructor takes the argument by non-const reference (can't accept a temporary from CTest(5) - VC++ may accept it as a non-standard compiler extension, though).

The morale is: there is no easy way to tell where and how many times the copy constructor is called in a program by looking at the code. Copying can be often omitted, and therefore you should never rely on the side-effects of the copy constructor. If it does what it is supposed to do, then it shouldn't matter to you if the compiler eliminates some unnecessary copy constructor calls.