## 对象的初始化和清理
拷贝构造函数调用时机
class Person
{
public:
Person() {
cout << "Person 默认构造函数调用" << endl;
};
Person(int age) {
this->m_age = age;
cout << "Person 有参构造调用" << endl;
};
~Person()
{
cout << "Person 析构函数调用" << endl;
};
Person(const Person& p)
{
cout << "Person 拷贝构造" << endl;
this->m_age = p.m_age;
};
private:
int m_age;
};
C++中拷贝构造函数调用时机通常有三种情况
-
使用一个已经创建完毕的对象来初始化一个新对象
void test01() { Person p1(10); Person p2 = p1; }
-
值传递的方式给函数参数传值
void doWork(Person p) { p; } void test02() { Person p; doWork(p); }
-
以值方式返回局部对象
Person doWork2() { Person p1; return p1; } void test03() { Person p = doWork2(); }
构造函数调用规则
默认情况下,C++编译器至少给一个类提供三个函数
- 默认构造函数,无参、函数体为空
- 默认析构函数,无参、函数体为空
- 默认拷贝构造函数,对属性进行值拷贝
构造函数调用规则如下
- 如果用户定义有参构造函数,C++不再提供默认无参构造函数,但是会提供默认拷贝构造
- 如果用户定义拷贝构造,C++不会提供其他构造函数
深拷贝和浅拷贝
class Person
{
public:
Person() {
cout << "Person 的默认构造函数" << endl;
};
Person(int age, int height)
{
this->m_age = age;
m_Height = new int(height);
cout << "Preson 的有参构造函数" << endl;
}
~Person() {
if (m_Height)
{
delete m_Height;
m_Height = nullptr;
}
cout << "Person 的析构函数调用" << endl;
};
int m_age;
int *m_Height;
private:
};
浅拷贝:简单的复制拷贝操作
Person(const Person &p)
{
cout << "Person 的拷贝构造函数的调用" << endl;
m_age = p.m_age;
m_Height = p.m_Height; // 编译器默认实现
}
深拷贝:在堆区重新申请空间,进行拷贝操作
Person(const Person &p)
{
cout << "Person 的拷贝构造函数的调用" << endl;
m_age = p.m_age;
m_Height = new int(*p.m_Height);
}
对与堆区申请的空间,浅拷贝进行简单的赋值拷贝操作,拷贝完成后,两个对象的指针指向堆区的同一个空间,深拷贝在堆区重新申请空间,进行拷贝操作。编译器提供的拷贝构造会进行浅拷贝操作。
浅拷贝带来的问题就是堆区的内存重复释放
初始化列表
语法:构造函数():属性1(值1), 属性2(值2), 属性3(值)...{}
类对象作为类成员
当类中成员是其他类对象时,我们称该成员为对象成员
构造顺序是:先调用对象成员的构造,再调用本类的构造
析构顺序是:先析构本类的构造,再析构对象成员的构造。
静态成员
静态成员变量
- 所有对象共享一份数据
- 编译阶段分配内存
- 类内声明,类外初始化
静态成员函数
- 所有对象公用一个函数
- 静态成员函数只能访问静态成员变量,不能访问非静态成员变量