复制构造

复制构造函数被调用的三种情况

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)

  1. - 复制对象把它作为参数传递给函数。
  2. ```cpp
  3. void fun1(Point p){
  4. cout<<p.get(X)<<endl;
  5. }
  6. //调用语句:
  7. fun1(b);
  • 复制对象,并从函数返回这个对象。 ```cpp Point fun2(){

    return Point(1,2);

}

//调用语句: b=fun2();

  1. <a name="QR6yT"></a>
  2. ### 浅层复制
  3. 实现对象间数据元素的一一对应复制。
  4. <a name="rNptv"></a>
  5. ### 深层复制
  6. 当被复制的对象数据成员是指针类型时,不是复制该指针成员本身,而是将指针(或引用)所指对象进行复制。 <br />实现深层copy的方法,就是在类中手动而外添加copy构造函数,如下:
  7. ```cpp
  8. 类名::类(const 类名&对象名)//复制构造函数的实现
  9. {
  10. 函数体
  11. }

代码如:

  1. class A {
  2. public:
  3. A() {
  4. m = new int[4]{ 1,2,3,4 };
  5. std::cout << "constructor" << std::endl;
  6. }
  7. ~A() {
  8. if (m != nullptr) {
  9. delete[] m;
  10. }
  11. }
  12. A(const A& a) {
  13. this->m = new int[4];
  14. memcpy(a.m, this->m, this->len * sizeof(int));
  15. std::cout << "copy constructor" << std::endl;
  16. }
  17. // 移动构造
  18. A(A&& a) : m(a.m) {
  19. a.m = nullptr;
  20. std::cout << "move constructor" << std::endl;
  21. }
  22. // 赋值操作符重载
  23. A& operator= (const A& a) {
  24. memcpy(a.m, this->m, this->len * sizeof(int));
  25. std::cout << "operator" << std::endl;
  26. return *this;
  27. }
  28. private:
  29. int len = 4;
  30. int* m = nullptr;
  31. };
  32. A getA(A a) {
  33. return a;
  34. }
  35. int main(void)
  36. {
  37. A a; // construct
  38. A b = a; // copy construct
  39. A c(a); // copy construct
  40. A d; // construct
  41. d = a; // operate
  42. A e = getA(a); // construct, move construct
  43. return 0;
  44. }

为什么需要深层复制

先看一个例子

  1. #include <iostream>
  2. #include <cassert>
  3. using namespace std;
  4. class Point {
  5. public:
  6. Point() : x(0), y(0) {
  7. cout<<"Default Constructor called."<<endl;
  8. }
  9. Point(int x, int y) : x(x), y(y) {
  10. cout<< "Constructor called."<<endl;
  11. }
  12. ~Point() { cout<<"Destructor called."<<endl; }
  13. int getX() const { return x; }
  14. int getY() const { return y; }
  15. void move(int newX, int newY) {
  16. x = newX;
  17. y = newY;
  18. }
  19. private:
  20. int x, y;
  21. };
  22. class ArrayOfPoints {
  23. //动态数组类
  24. public:
  25. ArrayOfPoints(int size) : size(size) {
  26. points = new Point[size];
  27. }
  28. ~ArrayOfPoints() {
  29. cout << "Deleting..." << endl;
  30. delete[] points;
  31. }
  32. Point& element(int index) {
  33. assert(index >= 0 && index < size);
  34. return points[index];
  35. }
  36. private:
  37. Point *points; //指向动态数组首地址
  38. int size; //数组大小
  39. };
  40. int main() {
  41. int count;
  42. cout << "Please enter the count of points: ";
  43. cin >> count;
  44. ArrayOfPoints pointsArray1(count); //创建对象数组
  45. pointsArray1.element(0).move(5,10);
  46. pointsArray1.element(1).move(15,20);
  47. ArrayOfPoints pointsArray2(pointsArray1); //创建副本
  48. cout << "Copy of pointsArray1:" << endl;
  49. cout << "Point_0 of array2: " << pointsArray2.element(0).getX() << ", "
  50. << pointsArray2.element(0).getY() << endl;
  51. cout << "Point_1 of array2: " << pointsArray2.element(1).getX() << ", "
  52. << pointsArray2.element(1).getY() << endl;
  53. pointsArray1.element(0).move(25, 30);
  54. pointsArray1.element(1).move(35, 40);
  55. cout<<"After the moving of pointsArray1:"<<endl;
  56. cout << "Point_0 of array2: " << pointsArray2.element(0).getX() << ", "
  57. << pointsArray2.element(0).getY() << endl;
  58. cout << "Point_1 of array2: " << pointsArray2.element(1).getX() << ", "
  59. << pointsArray2.element(1).getY() << endl;
  60. return 0;
  61. }

运行代码出现了错误,是因为复制的对象虚构函数执行两次,第一次已经析构了,对象已经不存在,再次析构编译器就会不知道析构对象是什么,报错。
所以需要而外添加复制构造函数,添加代码如下:

  1. ArrayOfPoints::ArrayOfPoints(const ArrayOfPoints& v) {
  2. size = v.size;
  3. points = new Point[size];
  4. for (int i = 0; i < size; i++)
  5. points[i] = v.points[i];
  6. }

疑惑

本人测试,新的编译器会自动帮我们完成深copy,不报错

  1. class Test {
  2. public:
  3. Test(int* p) { p = p; };
  4. int* p;
  5. //Test (const Test &obj) {
  6. // p = new int();
  7. // p = obj.p;
  8. // cout << "复制构造" << endl;
  9. //}
  10. ~Test() {
  11. delete p;
  12. }
  13. };
  14. int main()
  15. {
  16. // cout<<[](int x, int y) {return x + y; }(2, 5);
  17. auto sum= [](int x, int y) {return x + y; };
  18. //cout<<sum(1, 2);
  19. int a = 10;
  20. int*b = &a;
  21. Test myt(b);
  22. Test myt2 = myt;//写法copy1
  23. Test myt3(myt);//写法copy2
  24. }

拷贝构造函数:https://www.runoob.com/cplusplus/cpp-copy-constructor.html