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

What's the difference between class reference and class object when the function return class object in C++?

本文关键字:对象 之间 区别 什么 引用 函数 C++ 返回      更新时间:2023-10-16

为了明确我的问题,我举了一个例子:

  #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或类引用obj11。对我来说,它们是相同的,我想知道它们之间有什么区别,鼓励哪种练习。

编辑: 它可以在Visual Studio 2010上编译。

Abc &obj11 = fun1();

此行使程序格式不正确;C++规范禁止临时绑定到未const的引用。 兼容的C++编译器会发出与此效果相关的错误。 据推测,您正在使用 Microsoft Visual C++ 编译器,该编译器以允许将临时引用绑定到与C++规范相矛盾的非const引用而闻名。

const Abc &obj11 = fun1();

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

在任何情况下,当将临时绑定到引用时,临时将

延长其生存期以匹配引用的生存期,因此当引用超出范围时,临时也将被删除。 换句话说,就生命周期语义而言,它等同于第 1 Abc obj1 = fun1();行。如果您使用的是省略副本的编译器,则在这两种情况下都将省略所有副本。如果不省略副本,则参考案例将少涉及一个副本:

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

请注意,一个体面的优化编译器将完全优化所有副本以及参考细节,从而为问题中的两种情况留下相同的程序集输出。

(如果您有兴趣,这里有一个测试用例,其中的代码略有调整。请注意,除非禁用复制省略,否则在这两种情况下都不会创建副本。


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

它们是不一样的。在行中

obj1 = fun1();

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

在行中

Abc &obj11 = fun1();

你捕获了对象 fun1() 创建了一个引用。 现在你只有一个对象,用引用捕获。

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