C++ 当我们通过值从方法返回对象时,为什么要调用复制构造函数

C++ 当我们通过值从方法返回对象时,为什么要调用复制构造函数,c++,copy-constructor,return-by-value,C++,Copy Constructor,Return By Value,当我们通过值从方法返回对象时,为什么调用复制构造函数。请看我下面的代码,我从一个方法返回一个对象,而返回控件则点击复制构造函数,然后返回。我不明白以下几点: 1) 为什么调用复制构造函数。 2) 哪个对象隐式传递给复制构造函数, 3) 复制构造函数将内容复制到哪个对象, 4) 返回时复制对象内容的必要性是什么。所以请帮忙 #include "stdafx.h" #include <iostream> #include <string> using namespace st

当我们通过值从方法返回对象时,为什么调用复制构造函数。请看我下面的代码,我从一个方法返回一个对象,而返回控件则点击复制构造函数,然后返回。我不明白以下几点:
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;
 }
#包括“stdafx.h”
#包括
#包括
使用名称空间std;
甲级
{
INTA,b;
公众:
类别a()
{
a=10;
b=20;
}
A类(A类和obj类)
{

我会试着一次回答所有的问题

你所观察到的行为是由于C++中的值返回对象的方式。首先,临时函数是由函数返回的值构造(或在C++ 11中移动),然后,如果这个返回值被用来初始化另一个对象,例如in:

Class c = fxn();
对象
c
是从该临时对象复制构造的(在c++11中是移动构造的)

这就是说,根据C++11标准第12/8.31段,允许一个实现删除一个或两个对复制或移动构造函数的调用,即使这些构造函数有副作用,并直接在
C
中构造函数的返回值:

当满足某些条件时,允许实现省略类的复制/移动构造 对象,即使为复制/移动操作选择了构造函数和/或为对象选择了析构函数 有副作用。在这种情况下,实现将处理省略的复制/移动的源和目标 操作作为简单的两种不同的方式引用同一对象,并销毁该对象 在两个对象在没有优化的情况下会被销毁的时间较晚时发生。122 在以下情况下允许省略复制/移动操作,称为复制省略 可以合并以消除多个副本)

-在具有类返回类型的函数中的
return
语句中,当表达式是 具有相同cv的非易失性自动对象(,函数或catch子句参数除外) 类型作为函数返回类型,可以通过构造 自动对象直接输入函数的返回值

-[……]

-复制/移动未绑定到引用(12.2)的临时类对象时 对于具有相同cv类型的类对象,可以通过 将临时对象直接构造到省略的复制/移动的目标中

-[……]

我之所以这样写道,在您的具体案例中,只有一个对复制或移动构造函数的调用可以省略,原因是上面标准引用的第一个项目符号中的粗体句子:

[…](函数或catch子句参数除外)[…]

如果返回函数的参数,则禁止复制省略

另外请注意,您的构造函数的签名应为:

Class(Class const& c)
//          ^^^^^
您没有理由接受复制构造函数中对non-
const
的左值引用,因为您不打算修改要从中复制的对象

更糟糕的是,上述操作会阻止右值(如临时值)的复制构造,因此无法编译以下代码:

Class foo() { return Class(); }
即使允许实现省略副本,仍然应该存在一个可行且可访问的副本构造函数(或者移动构造函数,如果我们谈论的是移动的话)

ClassA function (ClassA &str)
{
  return str;
}

object
str
将复制类型为
ClassA
的临时对象中构造的对象以供进一步使用。但是,由于优化,编译器可以忽略它。

函数返回一个对象。因此,该对象必须存在。因此,该对象必须从某处创建。显然,这意味着它的一个构造函数必须是问题是,哪一个


由于您选择了
返回str;
,因此这是创建它时应使用的指令。否则,您如何使用该返回指令来创建和返回对象,而不使用复制构造函数?很明显,您需要使用
str
来初始化返回值,因此您不会使用其他选项(无参数构造函数).

调用复制构造函数是因为您是通过值而不是通过引用调用的。因此,必须从当前对象实例化一个新对象,因为该对象的所有成员在返回的实例中都应该具有相同的值。否则,您将返回对象本身,而该对象将通过引用返回。在这种情况下修改引用对象也会更改原始对象。这通常不是按值返回时需要的行为。

您是否理解,如果从函数返回对象,则必须创建该对象?为什么我们需要创建该对象,我只是返回在主函数o中构造的接收对象仅。如果函数返回一个对象,它将返回一个对象,不多也不少。您将对另一个对象的引用作为参数传递的事实完全不会影响这些语义。必须返回一个对象。下面的代码:“ClassA str;ClassA str2=函数(str);”必须以两个对象结束,str和str2。只有一个构造函数根本无法完成。你需要创建两个对象。好的,Daniel,现在我得到了。谢谢你的帮助。这与你之前的问题非常相似