I wrote a small test program with a sample class containing also self-defined constructor, destructor, copy constructor and assignment operator. I was surprised when I realized that the copy constructor was not called at all, even though I implemented functions with return values of my class and lines like Object o1; Object o2(o1);
innerclass.hpp:
#include <iostream>
class OuterClass
{
public:
OuterClass()
{
std::cout << "OuterClass Constructor" << std::endl;
}
~OuterClass()
{
std::cout << "OuterClass Destructor" << std::endl;
}
OuterClass(const OuterClass & rhs)
{
std::cout << "OuterClass Copy" << std::endl;
}
OuterClass & operator=(const OuterClass & rhs)
{
std::cout << "OuterClass Assignment" << std::endl;
}
class InnerClass
{
public:
InnerClass() : m_int(0)
{
std::cout << "InnerClass Constructor" << std::endl;
}
InnerClass(const InnerClass & rhs) : m_int(rhs.m_int)
{
std::cout << "InnerClass Copy" << std::endl;
}
InnerClass & operator=(const InnerClass & rhs)
{
std::cout << "InnerClass Assignment" << std::endl;
m_int = rhs.m_int;
return *this;
}
~InnerClass()
{
std::cout << "InnerClass Destructor" << std::endl;
}
void sayHello()
{
std::cout << "Hello!" << std::endl;
}
private:
int m_int;
};
InnerClass innerClass()
{
InnerClass ic;
std::cout << "innerClass() method" << std::endl;
return ic;
}
};
innerclass.cpp:
#include "innerclass.hpp"
int main(void)
{
std::cout << std::endl << "1st try:" << std::endl;
OuterClass oc;
OuterClass oc2(oc);
oc.innerClass().sayHello();
std::cout << std::endl << "2nd try:" << std::endl;
OuterClass::InnerClass ic(oc.innerClass());
ic = oc.innerClass();
}
Output:
1st try:
OuterClass Constructor
OuterClass Copy
InnerClass Constructor
innerClass() method
Hello!
InnerClass Destructor
2nd try:
InnerClass Constructor
innerClass() method
InnerClass Constructor
innerClass() method
InnerClass Assignment
InnerClass Destructor
InnerClass Destructor
OuterClass Destructor
OuterClass Destructor
After some research I read that there is no guarantee that the compiler will use the explicitely defined copy constructor. I do not understand this behavior. Why does the copy constructor even exist then, if we do not know that it is called? How does the compiler decide if it uses it?
Or, even better, is there a way to force the compiler to use the self-defined copy constructor?