当我们按值从方法返回对象时,为什么要调用复制构造函数
Why is the copy constructor called when we return an object from a method by value
当我们按值从方法返回对象时,为什么要调用复制构造函数。请参阅我下面的代码,因为我从一个方法返回一个对象,而返回控件是点击复制构造函数然后返回。我不明白以下几点:
1( 为什么它调用复制构造函数
2( 哪个对象隐式传递给复制构造函数,
3( 复制构造函数将内容复制到哪个对象,
4( 在返回时复制对象内容的必要性是什么。所以请帮忙。
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class ClassA
{
int a, b;
public:
ClassA()
{
a = 10;
b = 20;
}
ClassA(ClassA &obj)
{
cout << "copy constructor called" << endl;
}
};
ClassA function (ClassA &str)
{
return str;
}
int main ()
{
ClassA str;
function(str);
//function(str);
return 0;
}
我会尝试同时回答所有问题。
您观察到的行为是由于在C++中按值返回对象的方式造成的。首先,一个临时对象是根据函数返回的值进行复制构造(或在C++11中进行移动构造(的。然后,如果这个返回值用于初始化另一个对象,例如:
Class c = fxn();
对象c
是从该临时对象复制构造的(或者在C++11中是移动构造的(。
也就是说,允许实现根据C++11标准的第12/8.31段消除对复制或移动构造函数的一个或两个调用,即使这些构造函数有副作用,并直接在c
:中构造函数的返回值
当满足某些条件时,允许实现省略类的复制/移动构造对象,即使为复制/移动操作选择的构造函数和/或对象的析构函数有副作用。在这种情况下,实现会处理省略的复制/移动的源和目标操作只是指代同一对象的两种不同方式,以及对该对象的破坏发生在两个对象在没有优化的情况下会被销毁的较晚时间。12在以下情况下允许省略复制/移动操作,称为复制省略(可以组合以消除多个副本(:
--在具有类返回类型的函数中的
return
语句中,当表达式是具有相同cv的非易失性自动对象(而不是函数或catch子句参数(不合格类型作为函数返回类型,可以通过构造来省略复制/移动操作自动对象直接输入函数的返回值--[…]
--尚未绑定到引用(12.2(的临时类对象何时被复制/移动对于具有相同cv不合格类型的类对象,可以通过将临时对象直接构建到省略的复制/移动的目标中
--[…]
我之所以写道,在您的特定情况下,只有一个对复制或移动构造函数的调用可以被忽略,是因为上面标准引用的第一个项目符号中的粗体句子:
[…](函数或catch子句参数除外([…]
如果返回函数的参数,则禁止复制省略。
还要注意,构造函数的签名应该是:
Class(Class const& c)
// ^^^^^
您没有理由在复制构造函数中接受对非const
的左值引用,因为您不会修改要从中复制的对象。
更糟糕的是,上述操作会阻止从右值(如临时值(复制构造,因此以下代码不会编译:
Class foo() { return Class(); }
即使允许一个实现消除副本,一个可行且可访问的副本构造函数(或者移动构造函数,如果我们谈论的是移动(仍然应该存在。
函数返回一个对象。因此,该对象必须存在。因此,必须从某个地方创建该对象。显然,这意味着应该使用其中一个构造函数。问题是,哪一个?
既然你选择了return str;
,这就是创建它的指令。否则你怎么能用这个返回指令来创建和返回一个对象,而不使用复制构造函数呢?很明显,您需要使用str
来初始化返回的值,所以您不会使用其他选项(无参数构造函数(。
ClassA function (ClassA &str)
{
return str;
}
对象str
将复制构造在类型为ClassA
的临时对象中以供进一步使用。然而,由于优化,编译器可以省略它。
- 为什么调用堆栈数组会导致内存泄漏
- 为什么调用复制构造函数而不是移动构造函数?
- C++继承 - 为什么调用父方法?
- 为什么调用没有正文的纯虚拟方法不会导致链接器错误?
- 为什么调用移动分配?
- 为什么调用复制构造函数来构造空unique_ptr向量?
- 为什么调用具有通用或 r 值引用的重载覆盖函数是不明确的?
- 为什么调用不明确的 ctor 时没有编译时错误?
- 为什么调用shared_from_this调用 std::终止
- 为什么调用 cout.operator<<(const char*) 打印地址而不是字符串? 如何创建一个函数本地静态"HashSet<char>"并初始化它一次?
- 为什么调用成员函数不调用该对象的 ODR-USE?
- 为什么调用复制构造函数,当我只返回对象 c++ 的引用时
- 为什么调用转发引用构造函数而不是复制构造函数?
- 为什么调用单例类 Qt 消息处理程序成员函数会出现错误:缺少参数列表
- 为什么调用超载构造函数会导致默认构造函数的调用
- C++为什么调用复制构造函数
- 为什么调用定义的构造函数会导致结构声明中出现错误,我该如何修复它
- 为什么调用 CUDA 内核函数时这个类成员变量没有改变
- 为什么调用复制构造函数而不是移动构造函数
- 为什么调用此constexpr静态成员函数时不将其视为constexpr