当函数在 C++ 中返回类对象时,类引用和类对象之间有什么区别?
What's the difference between class reference and class object when the function return class object in 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
或类引用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 a
和 A& a = b
不一样。 A a
堆栈上创建一个对象。 A& a = b
不会创建另一个对象,它只是用引用"捕获"一个对象。
- 通过插槽和信号在不同线程中的两个qt对象之间进行通信
- 在什么条件下使用 std::memcpy 在对象之间复制是安全的?
- std::memmove在同一对象之间是否始终安全
- 将基类分配给派生对象,反之亦然,以C++以及静态和动态对象之间的差异
- const auto & 和 auto & if reference 对象之间的区别是 const
- C++:在另外两个对象之间共享一个对象
- 拥有或在对象之间共享资源
- 为什么库API+编译器ABI足以确保具有不同版本gcc的对象之间的兼容性
- 迭代器和标量对象之间的未定义行为有什么区别吗?
- 运行线程和线程对象之间的关系
- 有没有办法在两个共享对象之间使用相同的全局变量?
- 通过 Boost Python 在C++对象之间传递共享指针的隔离错误
- C 存储两个类对象之间的差异
- C++ std::vector 创建对象然后添加对象与在向量中创建对象之间的区别?
- 对象 ** 到对象 * 之间的融合
- 使用多态性时在子对象之间进行转换?
- 比较类的两个对象之间的数据
- 在C 中,是否有可能在不兼容类型的std ::向量对象之间传输不同类型的缓冲区
- 不同类别的 2 个对象之间的信号/插槽
- 与不同父母的班级中的对象之间发送信号