- 复制构造
- 复制构造函数被调用的三种情况
- 深层复制?">为什么需要深层复制?
- 疑惑
复制构造
复制构造函数被调用的三种情况
1、定义一个对象时,以本类另一个对象作为初始值,发生复制构造;
2、如果函数的形参是类的对象,调用函数时,将使用实参对象初始化形参对象,发生复制构造;
3、如果函数的返回值是类的对象,函数执行完成返回主调函数时,将使用return语句中的对象初始化一个临时无名对象,传递给主调函数,此时发生复制构造。
如:
- 通过使用另一个同类型的对象来初始化新创建的对象。 ```cpp Point a(10,20);
Point b=a;
//分析:将对象a赋给参数p,即右边是p.x=a.p,左边x的x,y是b的xy分量(this->x=p.x)
- 复制对象把它作为参数传递给函数。
```cpp
void fun1(Point p){
cout<<p.get(X)<<endl;
}
//调用语句:
fun1(b);
复制对象,并从函数返回这个对象。 ```cpp Point fun2(){
return Point(1,2);
}
//调用语句: b=fun2();
<a name="QR6yT"></a>
### 浅层复制
实现对象间数据元素的一一对应复制。
<a name="rNptv"></a>
### 深层复制
当被复制的对象数据成员是指针类型时,不是复制该指针成员本身,而是将指针(或引用)所指对象进行复制。 <br />实现深层copy的方法,就是在类中手动而外添加copy构造函数,如下:
```cpp
类名::类(const 类名&对象名)//复制构造函数的实现
{
函数体
}
代码如:
class A {
public:
A() {
m = new int[4]{ 1,2,3,4 };
std::cout << "constructor" << std::endl;
}
~A() {
if (m != nullptr) {
delete[] m;
}
}
A(const A& a) {
this->m = new int[4];
memcpy(a.m, this->m, this->len * sizeof(int));
std::cout << "copy constructor" << std::endl;
}
// 移动构造
A(A&& a) : m(a.m) {
a.m = nullptr;
std::cout << "move constructor" << std::endl;
}
// 赋值操作符重载
A& operator= (const A& a) {
memcpy(a.m, this->m, this->len * sizeof(int));
std::cout << "operator" << std::endl;
return *this;
}
private:
int len = 4;
int* m = nullptr;
};
A getA(A a) {
return a;
}
int main(void)
{
A a; // construct
A b = a; // copy construct
A c(a); // copy construct
A d; // construct
d = a; // operate
A e = getA(a); // construct, move construct
return 0;
}
为什么需要深层复制?
先看一个例子
#include <iostream>
#include <cassert>
using namespace std;
class Point {
public:
Point() : x(0), y(0) {
cout<<"Default Constructor called."<<endl;
}
Point(int x, int y) : x(x), y(y) {
cout<< "Constructor called."<<endl;
}
~Point() { cout<<"Destructor called."<<endl; }
int getX() const { return x; }
int getY() const { return y; }
void move(int newX, int newY) {
x = newX;
y = newY;
}
private:
int x, y;
};
class ArrayOfPoints {
//动态数组类
public:
ArrayOfPoints(int size) : size(size) {
points = new Point[size];
}
~ArrayOfPoints() {
cout << "Deleting..." << endl;
delete[] points;
}
Point& element(int index) {
assert(index >= 0 && index < size);
return points[index];
}
private:
Point *points; //指向动态数组首地址
int size; //数组大小
};
int main() {
int count;
cout << "Please enter the count of points: ";
cin >> count;
ArrayOfPoints pointsArray1(count); //创建对象数组
pointsArray1.element(0).move(5,10);
pointsArray1.element(1).move(15,20);
ArrayOfPoints pointsArray2(pointsArray1); //创建副本
cout << "Copy of pointsArray1:" << endl;
cout << "Point_0 of array2: " << pointsArray2.element(0).getX() << ", "
<< pointsArray2.element(0).getY() << endl;
cout << "Point_1 of array2: " << pointsArray2.element(1).getX() << ", "
<< pointsArray2.element(1).getY() << endl;
pointsArray1.element(0).move(25, 30);
pointsArray1.element(1).move(35, 40);
cout<<"After the moving of pointsArray1:"<<endl;
cout << "Point_0 of array2: " << pointsArray2.element(0).getX() << ", "
<< pointsArray2.element(0).getY() << endl;
cout << "Point_1 of array2: " << pointsArray2.element(1).getX() << ", "
<< pointsArray2.element(1).getY() << endl;
return 0;
}
运行代码出现了错误,是因为复制的对象虚构函数执行两次,第一次已经析构了,对象已经不存在,再次析构编译器就会不知道析构对象是什么,报错。
所以需要而外添加复制构造函数,添加代码如下:
ArrayOfPoints::ArrayOfPoints(const ArrayOfPoints& v) {
size = v.size;
points = new Point[size];
for (int i = 0; i < size; i++)
points[i] = v.points[i];
}
疑惑
本人测试,新的编译器会自动帮我们完成深copy,不报错
class Test {
public:
Test(int* p) { p = p; };
int* p;
//Test (const Test &obj) {
// p = new int();
// p = obj.p;
// cout << "复制构造" << endl;
//}
~Test() {
delete p;
}
};
int main()
{
// cout<<[](int x, int y) {return x + y; }(2, 5);
auto sum= [](int x, int y) {return x + y; };
//cout<<sum(1, 2);
int a = 10;
int*b = &a;
Test myt(b);
Test myt2 = myt;//写法copy1
Test myt3(myt);//写法copy2
}
拷贝构造函数:https://www.runoob.com/cplusplus/cpp-copy-constructor.html