C++ 拷贝构造函数
2020-11-09 本文已影响0人
lieon
拷贝构造函数
- 拷贝构造函数是一种构造函数
- 当利用已存在的对象创建一个新的对象时(类似于拷贝),就会调用新对象的拷贝构造函数进行初始化
- 拷贝构造函数的格式固定的,接收一个const引用作为参数
class Car {
int m_price;
int m_length;
public:
Car(int price, int length = 0): m_price(price), m_length(length) {}
Car(const Car &car) {
m_price = car.m_price;
m_length = car.m_length;
}
};
调用父类的拷贝函数
class Person {
int m_age;
public:
Person(int age = 0): m_age(age) {}
Person(const Person &person): m_age(person.m_age) {}
};
class Student: public Person {
int m_score;
public:
Student(int age = 0, int score = 0): Person(age), m_score(score) { }
Student(const Student &student): Person(student), m_score(student.m_score) { }
};
void test() {
Car car1(10);
Car car2(100, 5);
// 利用car2对象创建car3对象,会调用car3对象的拷贝构造函数进行初始化
Car car3(car2);
Car car4 = car2; // 等价于 Car car4(car2)
Car car5(100, 100);
Car car6;
// 这里复制操作,直接将car5的8个字节数据拷贝到car3的8个字节
// 但是这个并不会创建新对象,所以不会调用拷贝函数
car6 = car5;
car6.m_length = car5.m_length;
car6.m_price = car5.m_price;
}
浅拷贝,深拷贝
- 编译器默认提供的拷贝是浅拷贝(shallow copy)
- 将一个对象中所有成员变量的值拷贝到另一个对象(简单的赋值操作)
- 如果对象某个成员变量是个指针,只会拷贝指针中存储的地址值,并不会拷贝指针指向的内存空间
- 可能会导致堆空间多次free问题
- 如果需要实现深拷贝(deep copy),就需要自定拷贝构造函数
- 将指针类型的成员变量所指向的内存空间,拷贝到新的内存空间
- 在堆区重新申请空间,进行拷贝操作
- 总结:如果有对象属性在堆区开辟的,一定要提供拷贝构造函数,进行深拷贝
class Car {
int m_price;
char *m_name;
public:
Car(int price, const char *name) {
m_name = new char[strlen(name) + 1] {};
strcpy(m_name, name);
}
Car(const Car &car): m_price(car.m_price) {
if (car.m_name == nullptr) {
return;
}
strcpy(m_name, car.m_name);
}
~Car() {
if (m_name != nullptr) {
delete[] m_name;
m_name = nullptr;
}
}
};
void testCar() {
Car car1(100, "bmw");
// 将car1的内存空间(8个字节)覆盖car2的内存空间(8个字节)
Car car2 = car1;
}
对象参数和返回值
- 使用对象类型作为函数的参数或者返回值,可能会产生一些不必要的中间对象(多次调用了拷贝构造函数)
void test1(Car car) {
}
Car test2() {
Car car(20, "3");
return car;
}
void testCar() {
Car car1(100, "bmw"); // Car(int price, const char *name)
test1(car1); // Car(const Car &car)
Car car2 = test2(); // Car(const Car &car)
Car car3(30, "3");// Car(int price, const char *name)
car3 = test2(); // Car(const Car &car)
}
# 隐式构造
- C++中存在隐式构造的现象:某些情况下,会隐式调用单参数的构造函数
```C++
void test1(Car car) {
}
Car test2() {
return 70;
}
void test() {
Car car1 = 10; // Car(int price)
Car car2(20); // Car(int price)
car2 = 30; // Car(int price)
test1(40); // Car(int price)
Car car3 = test2(); // Car(int price)
}
- 可以通过关键字 *explic禁止调用隐式构造
explicit Car(int price, const char *name) {
m_name = new char[strlen(name) + 1] {};
strcpy(m_name, name);
}
编译自动生成的构造函数
- C++的编辑器在某些特定的情况下,会给类自动生成无参的构造函数,比如
- 成员变量在声明的同时进行了初始化
- 有定义虚函数
- 虚继承了其他类
- 包含了某些对象类型的成员,且这个成员有构造函数(编译器生成或自定义)
- 父类有构造函数(编译器生成或自定义)
- 总结一下
- 对象创建后,需要做一些额外操作时(比如内存操作,函数调用),编译器一般都会为其自动生成无参的构造函数