为什么我需要类型T的复制构造函数?

时间:2018-03-14 11:41:31

标签: c++ templates copy-constructor

当需要复制构造函数时,我有点不确定。例如,给定此功能:

template<class T>
T max(const T* array, int size) {
    T result = array[0];
    for (int i = 1; i < size; ++i) {
        if (result < array[i]) {
            result = array[i];
        }
    }
    return result;
}

我需要T类型的复制构造函数的原因是什么?我认为一定是因为我们以价值回报。此行T result = array[0];是否还需要复制构造函数?

2 个答案:

答案 0 :(得分:5)

  

我需要copy constructor类型T的原因是什么?

T result = array[0];

这称为复制初始化,并调用类型T的复制构造函数。类型T要求此行的复制构造函数成功。

  

我认为它必须是因为我们会返回一个值,因此copy constructor类型需要T

return result;

在大多数情况下,您的假设对于返回值是正确的。但是,在这种情况下,定义复制构造函数并不是必需的。要实现move semantics,您可以实现一个移动构造函数,它将不再需要复制构造函数,因为局部变量result将被移动&#34;而不是&#34;复制&#34;从。移动语义从函数返回时不需要大型对象的不必要副本,因为在函数返回后将无法访问这些大对象。

答案 1 :(得分:1)

这已在这里得到解答:

  

What's the difference between assignment operator and copy constructor?

所以问题是:

复制构造函数用于从其他对象的数据初始化以前未初始化的对象。

赋值运算符用于将先前初始化的对象的数据替换为其他对象的数据。

以下是一个例子:

#include <iostream>

using namespace std;


class MyClass{
public:
  MyClass(){
    cout << "Default ctor\n";
  }

  MyClass(const MyClass& copyArg){
    cout << "Copy ctor\n";
  }

  MyClass(MyClass&& moveArg){
    cout << "Move ctor\n";
  }

  void operator=(const MyClass& assignArg){
    cout << "Assignment operator\n";
  }

  bool operator<(const MyClass& comparsionArg) const {
    return true;
  }
};

template<class T>
T max(const T* array, int size) {
    T result = array[0];
    for (int i = 0; i < size; ++i) {
        if (result < array[i]) {
            result = array[i];
        }
    }
    return result;
}


int main(){

  MyClass arr[1];

  const MyClass& a = max(arr, 1);

  return 0;
}

要了解到底发生了什么we need to compile with -fno-elide-constructors

输出结果为:

Default ctor
Copy ctor
Assignment operator
Move ctor

所以在这里,对于一个数组元素,在此行调用默认构造函数

MyClass arr[1];

然后我们初始化一个以前未初始化的对象,并调用复制构造函数

T result = array[0];

然后我们对以前初始化的对象和赋值运算符进行了分配:

result = array[i];

在我们需要在函数范围之外创建对象之后,因为我们按值返回并且为移动构造函数调用:

return result;

然后将main范围内用移动构造函数构造的对象绑定到const引用:

const MyClass& a = max(arr, 1);