Skip to content

C++ 拷贝构造

拷贝构造发生在以一个对象作为参照进行新的对象创建的过程中

其与构造函数和析构函数息息相关

构造函数

创建对象调用的函数

无返回值,与类名一致

  • 一般对类内的数据进行初始化
默认构造函数
cpp
#include <string>
class Person{
  public: 
  Person() = default;  // 显式默认构造
  private:
   std::string name{"Alpha"};
}

析构函数

销毁对象调用的函数

无返回值,使用 ~

  • 对类中数据分配的资源进行销毁
  • 在有堆内存分配时,必须在析构中销毁,否则可能导致内存泄露

拷贝构造函数

  • 以其他对象为模版进行的构造
  • 函数传参时作为值传参,引发拷贝构造
cpp
#include <iostream>
#include <string>
// Define a Person Class
class Person {
  friend void t_copy_constructor_value(Person person);
  friend void t_copy_constructor_ref(const Person &person);

public:
  Person() = default;
  Person(const Person &person) {
    std::cout << "default copy constructor" << std::endl;
    this->name = person.name;
  }
  ~Person() = default;

private:
  std::string name{"Alpha"};
};

// 传参构造
void t_copy_constructor_value(Person person) {
  // 会有一次输出 default copy constructor
  std::cout << person.name << std::endl;
}
// 引用传递则无构造
void t_copy_constructor_ref(const Person &person) {
  std::cout << person.name << std::endl;
}

// Main Func
int main(int argc, char *argv[]) {
  Person person_a;                    // 默认构造
  Person person_b(person_a);          // 拷贝构造
  t_copy_constructor_value(person_a); // 函数值传递
  t_copy_constructor_ref(person_a);
  return 0;
}

浅拷贝与深拷贝

浅拷贝
  • 默认拷贝构造是浅拷贝,只会对类内数据和指针进行拷贝,但不会对指针指向的对象进行拷贝
  • 两个对象的内部指针会指向同一块内存
  • 析构时,同一块内存会delete两次,程序崩溃
#include <iostream>
// Define a Person Class
class Person {
public:
	//默认浅拷贝
  Person() : name(new char[32]) { std::strcpy(name, "Alpha"); }
  ~Person() { delete[] name; };

private:
  char *name;
};

// Main Func
int main(int argc, char *argv[]) {
  Person person_a; // 默认构造
  Person person_b(person_a); // 默认拷贝 是浅拷贝
  return 0;
}
深拷贝
  • 对象B对A进行深拷贝,各自的指针指向的是各自持有的内存
  • 析构时,两者相互隔离,无内存隐患
cpp
#include <iostream>
// Define a Person Class
class Person {
public:
  Person() : name(new char[32]) { std::strcpy(name, "Alpha"); }
  // 自定深拷贝构造
  Person(const Person &other) : name(new char[32]) {
    std::strcpy(name, other.name);
  }
  ~Person() { delete[] name; };

private:
  char *name;
};

// Main Func
int main(int argc, char *argv[]) {
  Person person_a; // 构造
  Person person_b(person_a);//深拷贝
  return 0;
}