当函数在C ++中返回类对象时,类引用和类对象之间的区别是什么?

时间:2015-01-07 16:24:10

标签: c++

为了明确我的问题,我举了以下例子:

  #include <iostream>   


   class Abc
    {
       public:
        int a;
        int b;
        int c;
     };
     class Abc  fun1()
      {
         Abc obj;
         obj.a = 3;
         obj.b = 4;
         obj.c = 5;
          return obj;

        };

       int main ()
       {
          Abc obj1;
          obj1 = fun1();
          std::cout<<"obj1 address is "<<&obj1<<std::endl;

          Abc &obj11 = fun1();
          std::cout<<"obj11 address is "<<&obj11<<std::endl;



         return 0;
 }

正如您所看到的,函数的返回值是一个类对象,当您调用此函数来创建类对象时,您可以使用类对象obj1或类引用{{1 }}。对我来说,他们是一样的,我想知道他们之间的区别是什么以及鼓励哪种做法。

修改   它可以在Visual Studio 2010上编译。

2 个答案:

答案 0 :(得分:1)

他们不一样。 在行

obj1 = fun1();

fun1()创建一个对象,然后obj1 COPIES 它的内容。所以你有两个对象,一个是匿名的,你不能再使用了,而obj1就是它的精确副本。

Abc &obj11 = fun1();

你抓住了对象fun1()创建了哪个引用。现在你只有 ONE 对象,被一个引用抓住了。

请注意A aA& a = b不一样。 A a在堆栈上创建一个对象。 A& a = b不创建另一个对象,只是用引用“捕获”一个对象。

答案 1 :(得分:1)

Abc &obj11 = fun1();

此行使程序格式不正确; C ++规范禁止将临时值绑定到不是const的引用。兼容的C ++编译器会发出此错误。据推测,您使用的是Microsoft Visual C ++编译器,众所周知,该编译器允许将临时绑定到非const引用,与C ++规范相矛盾。

const Abc &obj11 = fun1();

此行格式正确,它会导致临时绑定到引用。

在任何情况下,当临时绑定到引用时,临时将延长其生命周期以匹配引用的生命周期,因此当引用超出范围时,临时也将被销毁。换句话说,就寿命语义而言,它等同于行Abc obj1 = fun1(); 1 。如果您正在使用省略副本的编译器,则在两种情况下都将省略所有副本。如果没有删除副本,则参考案例将减少一份副本:

  • 值的情况下,返回的对象将被复制到临时然后销毁,并将临时复制到obj1然后销毁。
  • 参考案例,将返回的对象复制到临时然后销毁,并将临时绑定到引用。

请注意,一个不错的优化编译器将完全优化所有副本以及参考细节,为您提出相同的装配输出。

(如果您有兴趣,请here is a test case稍微调整一下代码中的问题。请注意,除非禁用了复制省略,否则不会复制任何副本。)


1 请注意,这与您问题中的代码Abc obj1; obj1 = fun1();不同。我故意改变它,因为你写的代码不能直接比较,因此比较它们没有多大意义。如果您将其重写为Abc obj1 = fun1();,则可以比较两行,因为Abc obj1; obj1 = fun1();涉及默认构造,然后是复制分配。