提问人:Paul Manta 提问时间:3/20/2011 最后编辑:mpmPaul Manta 更新时间:6/28/2021 访问量:83539
复制构造函数和赋值运算符
The copy constructor and assignment operator
问:
如果我重写,复制构造函数会自动使用 new 运算符吗?同样,如果我定义一个复制构造函数,会自动从复制构造函数“继承”行为吗?operator=
operator=
答:
13赞
Erik
3/20/2011
#1
不。除非您定义 copy ctor,否则将生成默认值(如果需要)。除非定义 operator=,否则将生成默认值(如果需要)。它们不相互使用,您可以独立更改它们。
0赞
Jonathan Wood
3/20/2011
#2
不,它们不是同一个运算符。
57赞
Saurabh Gokhale
3/20/2011
#3
不,它们是不同的运算符。
复制构造函数用于创建新对象。它将现有对象复制到新构造的对象。复制构造函数用于从旧的实例初始化新实例 实例。当按值将变量传递到函数中时,不一定调用它 或作为函数的返回值。
赋值运算符用于处理已存在的对象。赋值运算符用于将现有实例更改为 与右值相同的值,这意味着实例必须 如果它有内部动态内存,则销毁并重新初始化。
有用的链接:
评论
0赞
Alcott
9/12/2011
@Prasoon,我不太明白,当按值将变量传递到函数中或作为函数的返回值时,为什么不调用复制构造函数?什么是 RVO?
0赞
Ghita
11/16/2012
@Alcottreturn价值优化
0赞
jupp0r
1/27/2016
还有复制省略,它对函数参数做同样的事情
1赞
stijn
3/20/2011
#4
不。
5赞
Alexandre C.
3/20/2011
#5
不。它们是不同的对象。
如果您担心复制构造函数和赋值运算符之间的代码重复,请考虑以下习惯用语,称为 copy 和 swap:
struct MyClass
{
MyClass(const MyClass&); // Implement copy logic here
void swap(MyClass&) throw(); // Implement a lightweight swap here (eg. swap pointers)
MyClass& operator=(MyClass x)
{
x.swap(*this);
return *this;
}
};
这样,将使用 copy 构造函数来构建一个新对象,该对象将在函数退出时与旧对象交换并释放(内部有旧对象)。operator=
*this
this
评论
0赞
Alcott
9/12/2011
通过引用复制和交换的习惯,您是否暗示在 copy-ctor 中调用 operator= 不是一个好做法,反之亦然?
0赞
Alexandre C.
9/13/2011
@Alcott:你不要在复制构造函数中调用 operator=,而是反过来做,就像我展示的那样。
0赞
Johan Boulé
5/8/2016
为什么你的赋值运算符不采用常量引用?
0赞
Alexandre C.
5/8/2016
@JohanBoule:这在我的回答的维基百科链接中得到了解释,这个问题也解释了
1赞
Ray Cao
3/11/2021
#6
请考虑以下 C++ 程序。
注意:我的“Vector”类不是标准库中的类。
我的“Vector”类接口:
#include <iostream>
class Vector {
private:
double* elem; // elem points to an array of sz doubles
int sz;
public:
Vector(int s); // constructor: acquire resources
~Vector() { delete[] elem; } // destructor: release resources
Vector(const Vector& a); // copy constructor
Vector& operator=(const Vector& a); // copy assignment operator
double& operator[](int i){ return elem[i]; };
int size() const {return sz;};
};
我的“Vector”类成员实现:
Vector::Vector(int s) // non-default constructor
{
std::cout << "non-default constructor"<<std::endl;
elem = {new double[s]};
sz =s;
for (int i=0; i!=s; ++i) // initialize elements
elem[i]=0;
}
Vector::Vector(const Vector& a) // copy constructor
:elem{new double[a.sz]},
sz{a.sz}
{
std::cout << "copy constructor"<<std::endl;
for (int i=0; i!=sz; ++i) // copy elements
elem[i] = a.elem[i];
}
Vector& Vector::operator=(const Vector& a) // copy assignment operator
{
std::cout << "copy assignment operator"<<std::endl;
double* p = new double[a.sz];
for (int i=0; i!=a.sz; ++i)
p[i] = a.elem[i];
delete[] elem; // delete old elements
elem = p;
sz = a.sz;
return *this;
}
int main(){
Vector v1(1);
v1[0] = 1024; // call non-default constructor
Vector v2 = v1; // call copy constructor !!!!
v2[0] = 1025;
std::cout << "v2[0]=" << v2[0] << std::endl;
Vector v3{10}; // call non-default constructor
std::cout << "v3[0]=" << v3[0] << std::endl;
v3 = v2; // call copy assignment operator !!!!
std::cout << "v3[0]=" << v3[0] << std::endl;
}
然后,程序输出:
non-default constructor
copy constructor
v2[0]=1025
non-default constructor
v3[0]=0
copy assignment operator
v3[0]=1025
总结一下:
Vector v2 = v1;
导致调用复制构造函数。v3 = v2;
导致调用复制分配操作员。
在情况 2 中,对象已经存在(我们已经完成了:)。复制构造函数和复制赋值运算符之间有两个明显的区别。v3
Vector v3{10};
- 复制构造函数 无需删除旧元素,它只是一个新对象。(因为它
copy construct
Vector v2
) - copy 构造函数 NO NEED to return the pointer。(此外,所有构造函数都不返回值)。
this
评论