C++ 如果函数按值传递并按值返回,将调用复制构造函数多少次

C++ 如果函数按值传递并按值返回,将调用复制构造函数多少次,c++,copy-constructor,C++,Copy Constructor,我理解f(ClassA str)按值传递和按值返回,所以 f(str)调用复制构造函数2次 f(f(str))调用复制构造函数4次 str1=f(f(str))调用复制构造函数5次 但结果是2,3,3 此外,如果我将f的定义更改为classaf(ClassA&str),存在一个错误引用非常量的初始值必须是左值。这个错误怎么会发生呢 #include<iostream> using namespace std; class ClassA { int a, b; public

我理解
f(ClassA str)
按值传递和按值返回,所以

f(str)
调用复制构造函数2次

f(f(str))
调用复制构造函数4次

str1=f(f(str))
调用复制构造函数5次

但结果是2,3,3

此外,如果我将
f
的定义更改为
classaf(ClassA&str),
存在一个错误
引用非常量的初始值必须是左值。这个错误怎么会发生呢

#include<iostream>

using namespace std;

class ClassA
{
    int a, b;
public:
    ClassA()
    {
        a = 10;
        b = 20;
    }
    ClassA(const ClassA &obj)
    {
        a = obj.a; b = obj.b;
        cout << "copy constructor called" << endl;
    }
};

ClassA f(ClassA str)
{
    return str;
}

int main(){
       ClassA str;
       ClassA str1;
       str1 = f(f(str));

}
#包括
使用名称空间std;
甲级
{
INTA,b;
公众:
类别a()
{
a=10;
b=20;
}
A类(const ClassA&obj)
{
a=对象a;b=对象b;
coutUPD:
ClassA只显式声明复制构造函数。
因此,ClassA具有默认的复制赋值运算符

如果类定义没有显式声明复制赋值运算符,则隐式声明一个。 如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明 复制分配运算符定义为已删除,否则定义为默认值

而且没有默认移动构造函数

如果类X的定义没有显式声明移动构造函数,则非显式构造函数将隐式声明 声明为默认的当且仅当 (8.1)-X没有用户声明的副本构造函数, (8.2)-X没有用户声明的副本分配运算符, (8.3)-X没有用户声明的移动分配运算符,并且 (8.4)-X没有用户声明的析构函数

相反,移动构造函数ClassA使用复制构造函数

注意:如果未隐式声明或显式提供move构造函数,则表达式将 可能会调用移动构造函数,但可能会调用副本构造函数。-结束说明]

复制省略发生在f(f(str))中

在具有类返回类型的函数中的return语句中,当表达式是 与函数具有相同类型(忽略cv限定)的非易失性自动对象(…) 返回类型,通过直接构造自动对象可以省略复制/移动操作 进入函数调用的返回对象

摘要: f(str)默认情况下:复制构造函数+移动构造函数;在本例中:复制构造函数+复制构造函数

f(f(str))默认情况下:复制构造函数+复制省略+移动构造函数+移动构造函数;在这种情况下:复制构造函数+复制省略+复制构造函数+复制构造函数

str1=f(f(str))-在这种情况下:复制构造函数+复制省略+复制构造函数+复制构造函数+复制赋值运算符(非复制构造函数)

例如,如果在gcc中使用标志“-fno elide constructors”,则可能有另一个结果。它禁用复制省略

f(str)返回右值对象。在ClassA f(ClassA&str)中,使用左值引用。
有趣的是,ClassA f(constClassA&str)没有给出错误

复制构造函数将被调用多少次…--这取决于编译器、编译器版本、优化设置等。没有具体的答案。这是正确的吗,您可以精确地指出某个数字(在您的例子中为3)?调用复制构造函数的次数取决于编译器和各种优化设置。