为什么我需要类型 T 的复制构造函数?
Why do I need a copy constructor for type T?
我有点不确定什么时候需要复制构造函数。例如,给出这个函数:
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
的复制构造函数的原因是什么?我认为这一定是因为我们 return 按价值计算。这行T result = array[0];
是否也需要复制构造函数?
What is the reason that I need copy constructor
for the type T
?
T result = array[0];
这称为复制初始化并调用类型 T
的复制构造函数。键入 T
将 需要 一个复制构造函数才能使此行成功。
I think that it's must be because that we return by a value, and so we need copy constructor
for T
type.
return result;
在大多数情况下,您的假设对于 return 值是正确的。但是,在这种情况下没有必要定义复制构造函数。要实现 move semantics,您可以实现移动构造函数,这将消除对复制构造函数的需要,因为局部变量 result
将是 "moved" 而不是 "copied"。当从函数 returning 大对象时,移动语义消除了对大对象不必要副本的需要,因为在函数 return 之后将无法访问这些大对象。
这里已经回答了:
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 按值并为此 移动构造函数 调用:
return result;
然后将 在 main
范围内移动构造函数 构造的对象绑定到 const 引用:
const MyClass& a = max(arr, 1);
我有点不确定什么时候需要复制构造函数。例如,给出这个函数:
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
的复制构造函数的原因是什么?我认为这一定是因为我们 return 按价值计算。这行T result = array[0];
是否也需要复制构造函数?
What is the reason that I need
copy constructor
for the typeT
?
T result = array[0];
这称为复制初始化并调用类型 T
的复制构造函数。键入 T
将 需要 一个复制构造函数才能使此行成功。
I think that it's must be because that we return by a value, and so we need
copy constructor
forT
type.
return result;
在大多数情况下,您的假设对于 return 值是正确的。但是,在这种情况下没有必要定义复制构造函数。要实现 move semantics,您可以实现移动构造函数,这将消除对复制构造函数的需要,因为局部变量 result
将是 "moved" 而不是 "copied"。当从函数 returning 大对象时,移动语义消除了对大对象不必要副本的需要,因为在函数 return 之后将无法访问这些大对象。
这里已经回答了:
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 按值并为此 移动构造函数 调用:
return result;
然后将 在 main
范围内移动构造函数 构造的对象绑定到 const 引用:
const MyClass& a = max(arr, 1);