首页 > 解决方案 > 一个函数传值传值返回,拷贝构造函数会被调用多少次

问题描述

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

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

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

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

但结果是 2,3,3。

此外,如果我将定义更改fClassA f(ClassA &str),存在错误initial value of reference to non-const must be an lvalue。这个错误是怎么来的?

#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));

}

标签: c++copy-constructor

解决方案


UPD:ClassA 显式声明仅复制构造函数。所以,ClassA默认的复制赋值操作符

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

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

如果类 X 的定义没有显式声明移动构造函数,当且仅当 (8.1) - X 没有用户声明的复制构造函数,(8.2) - X 时,非显式类将被隐式声明为默认值没有用户声明的复制赋值运算符, (8.3) — X 没有用户声明的移动赋值运算符,并且 (8.4) — X 没有用户声明的析构函数。

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

注意:当移动构造函数没有被隐式声明或显式提供时,否则会调用移动构造函数的表达式可能会调用复制构造函数。——尾注]

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

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

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

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

str1 = f(f(str)) - 在这种情况下:拷贝构造函数 + 拷贝省略 + 拷贝构造函数 + 拷贝构造函数 + 拷贝赋值运算符(不是拷贝构造函数赋值运算符和拷贝构造函数有什么区别?

可能有另一个结果,例如,如果在 gcc 中使用标志“-fno-elide-constructors”。它禁用复制省略 禁用 g++ 的返回值优化

f(str)返回右值对象。在ClassA f(ClassA &str)中,您采用左值引用。有趣的是 ClassA f( const ClassA& str) 不会给出错误常量引用和左值


推荐阅读