Click here to Skip to main content
15,885,141 members
Please Sign up or sign in to vote.
4.00/5 (2 votes)
See more:
C++
#include <iostream>
#include <tchar.h>
using namespace std;

class Human
{
public:
    Human()
    {
      cout << _T("constructor is invoked.") << endl;
    }

    ~Human()
    {
        cout << _T("destructor is invkoed.") << endl;
    }

    Human(Human& obj)
    {
        cout << _T("copy constructor is invoked.") << endl;
    }
};

class School
{
public:
    Human GetPrincipal()
    {
        return m_Principal;
    }
public:
    Human& GetPrincipal1()
    {
        return m_Principal;
    }

private:
    Human m_Principal;
};

int main()
{
    School MIT;  //------------------------------->this call Human()
    Human Principal = MIT.GetPrincipal();  //----->this call Human(Human& obj)
    Human Principal1 = MIT.GetPrincipal1();//----->this call Human(Human& obj)
    getchar();
    return 0;
}


I compiled and executed the code above in VS2010, the result was:
constructor is invoked.
copy constructor is invoked.
copy constructor is invoked.

Here is my question:
Human Principal = MIT.GetPrincipal();
Human Principal1 = MIT.GetPrincipal1();
They have the same result, but GetPrincipal() and GetPrincipal1() are different in function return value. In my option, GetPrincipal() should result in the copy constructor of the Class Human being invoked twice, but is's only being invked once, why?

I am not a person in English speaking countries, My English is not good, maybe it's hard for you to anderstand my words, sorry for that and I am tring to improve it.

Thank you for your help.
Posted
Updated 30-Apr-12 22:10pm
v3
Comments
Emilio Garavaglia 2-May-12 3:55am    
The proper prototype for copy constructor is Human(const Human&), otherwise certain expression and standard library functions may not work.

The answer to your question is not trivial. What you are observing here is a phenomenon call "return value optimization" (RVO).

But let's start at the beginning. What did you expect your program to produce? I would have said:

// statement: School MIT; 
constructor is invoked.

// statement: Human Principal = MIT.GetPrincipal();
copy constructor is invoked.
copy constructor is invoked.

// statement: Human Principal1 = MIT.GetPrincipal1();
copy constructor is invoked.


Why should the first of the assignment statements involve two calls of the copy constructor? Well, one for generating the return value and one for assigning the return value to the variable Principal.

For the second statement we only expect the copy constructor to be called once, because the function returns a reference to the Human object, which does not involve the copy constructor.

When run in a debugger you can see that the first assignment does not produce two but just one call of the copy constructor. And that is due to a rule called "return value optimization". You find a nice article about it here:

Wikipedia: Return Value Optimization[^]

When the compile sees that the intermediate object generated as return value is just assigned again to another object and then destroyed, it is allowed to skip the generation of that intermediate object. And that's what is happening here.

Well observed, and an interesting question!
 
Share this answer
 
Comments
DIAN.WANG 2-May-12 9:01am    
Thank you for your answer, i am so happy cause what you said is just what i wanna know.
Because what you're invoking was class School, not class Human.
Pay attention to this class :
C#
class School
{
public:
    Human GetPrincipal() //<--------------- this call Human()
    {
        return m_Principal;
    }
public:
    Human& GetPrincipal1() //<------------- this call Human(Human& modi)
        return m_Principal;
    }
 
private:
    Human m_Principal;
};


In school class you called Human twice (Human and Human&), so when you're invoking school the result should be :
C#
int main(){
School MIT;
..
..
} 

constructor is invoked.
copy constructor is invoked.

so the rest would be resulted like this :
C#
int main(){
...
    Human Principal = MIT.GetPrincipal();
    Human Principal1 = MIT.GetPrincipal1();
...
...
}

copy constructor is invoked.
copy constructor is invoked.


So that's it.

--newmessage
 
Share this answer
 
v2
Comments
DIAN.WANG 1-May-12 4:18am    
Thank you for your answer, i have improve my question, I am sorry for my wrong code result,could you tell me why again or where i can find the knowledge for answering my question?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900