关于对象构造函数的质疑 [英] A quesion about the object constructor

查看:90
本文介绍了关于对象构造函数的质疑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#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;
}



我在VS2010中编译并执行了上面的代码,结果是:
构造函数被调用.
复制构造函数被调用.
复制构造函数被调用.

这是我的问题:
人类负责人= MIT.GetPrincipal();
人力Principal1 = MIT.GetPrincipal1();
它们具有相同的结果,但GetPrincipal()和GetPrincipal1()的函数返回值不同.在我的选择中,GetPrincipal()应该导致类Human的副本构造函数被调用两次,但是仅被调用一次,为什么?

我不是英语国家的人,我的英语不好,也许您很难理解我的语言,对此感到抱歉,我正努力改善它.

谢谢您的帮助.



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.

推荐答案

对于您的问题的回答并不简单.您在这里观察到的现象称为返回值优化"(RVO).

但是,让我们从头开始.您期望程序产生什么?我会说:

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.



为什么第一个赋值语句应该涉及复制构造函数的两次调用?好吧,一种用于生成返回值,另一种用于将返回值分配给变量Principal.

对于第二条语句,我们只希望复制构造函数被调用一次,因为该函数返回对Human对象的引用,该引用不涉及复制构造函数.

在调试器中运行时,您会看到第一个分配不会产生两个,而只会产生一个复制构造函数的调用.这是由于称为返回值优化"的规则所致.您可以在此处找到有关此文章的不错的文章:

Wikipedia:返回值优化 [ ^ ]

当编译器看到将作为返回值生成的中间对象再次分配给另一个对象然后销毁时,可以跳过该中间对象的生成.这就是这里发生的事情.

观察得很好,还有一个有趣的问题!



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!


因为您要调用的是School类,而不是Human类.
注意这节课:
Because what you''re invoking was class School, not class Human.
Pay attention to this class :
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;
};



在学校上课,您两次致电人类(Human and Human&),所以当您上学时,结果应该是:



In school class you called Human twice (Human and Human&), so when you''re invoking school the result should be :

int main(){
School MIT;
..
..
} 


构造函数被调用.
复制构造函数被调用.

所以剩下的就是这样:


constructor is invoked.
copy constructor is invoked.

so the rest would be resulted like this :

int main(){
...
    Human Principal = MIT.GetPrincipal();
    Human Principal1 = MIT.GetPrincipal1();
...
...
}


复制构造函数被调用.
复制构造函数被调用.


就这样.

--newmessage


copy constructor is invoked.
copy constructor is invoked.


So that''s it.

--newmessage


这篇关于关于对象构造函数的质疑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆