构造函数的类型
构造函数会在类每次实例化的时候自动调用,构造函数可以分成如下几类:
- 按照是否有参数分为:无参构造函数和有参构造函数,其中无参构造函数也是默认的构造函数
- 按照构造函数的类型分为:普通构造函数和拷贝构造函数
无参构造函数
#include <iostream>
#include <string>
using namespace std;
class test {
public:
test() {
cout << "test"<< endl; /* 实例化class test的时候自动调用 */
}
~test() {}
};
int main(int argc, char const *argv[]) {
test t; /* 会自动调用无参构造函数 */
return 0;
}
有参构造函数
#include <iostream>
#include <string>
using namespace std;
class test {
public:
test(int value) {
cout << "test value: " << value << endl;
}
~test() {}
};
int main(int argc, char const *argv[]) {
/* 1.括号法 */
test t1(1);
/* 2.显示法 */
test t2 = test(2);
/* 3.隐式转换法 */
test t3 = 3; /* 相当于:test t3 = test(3) */
return 0;
}
拷贝构造函数
#include <iostream>
#include <string>
using namespace std;
class test {
public:
/* 无参构造函数,为了测试创建一个无参构造函数 */
test() {}
/* 拷贝构造函数 */
test(const test& t) {
m_value = t.m_value;
}
~test() {}
int m_value;
};
int main(int argc, char const *argv[]) {
test t;
/* 1.括号法 */
t.m_value = 1;
test t1(t);
cout << "t1.m_value: "<< t1.m_value << endl;
/* 2.显示法 */
t.m_value = 2;
test t2 = test(t);
cout << "t2.m_value: " << t2.m_value << endl;
/* 3.隐式转换法 */
t.m_value = 3;
test t3 = t; /* 相当于:test t3 = test(t) */
cout << "t3.m_value: " << t3.m_value << endl;
return 0;
}
构造函数的规则
- 默认情况下,编译器会为一个类定义三个函数,默认构造函数(无参数,空实现),默认析构函数(无参数,空实现),默认拷贝函数(浅拷贝,对属性值进行拷贝)
- 如果用户定义了有参构造函数,那么编译器将不再定义默认的无参构造函数,但是会提供默认的拷贝函数
- 如果用户定义了拷贝函数,那么编译器将不再提供其他构造函数
拷贝构造函数的深拷贝和浅拷贝
默认的拷贝构造函数,是直接进行最简单的赋值拷贝操作,如果出现了指针相关操作的话,会出现因为是简单赋值导致的重复释放的问题。示例如下:
#include <iostream>
#include <string>
using namespace std;
class test {
public:
/* 定义有参构造函数 */
test(int value, int ptr_value) {
m_value = value;
m_ptr = new int(ptr_value);
}
/* 默认的拷贝构造函数,类似如下的代码,执行简单的赋值操作 */
// test(const test& t) {
// m_value = t.m_value;
// m_ptr = t.m_ptr;
// }
/* 定义拷贝构造函数,执行深拷贝,就是重新new一片空间,用来存放m_ptr的值,与原class的地址就不会冲突了 */
test(const test& t) {
m_value = t.m_value;
m_ptr = new int(*t.m_ptr);
}
~test() {
if (m_ptr != NULL) {
delete m_ptr;
m_ptr = NULL;
}
}
int m_value;
int* m_ptr;
};
void func() {
/* 实例化test class,调用定义的有参构造函数 */
test t1(10, 20);
/* 实例化test class,没有定义拷贝构造函数的话调用默认拷贝构造函数,有定义则使用定义的拷贝构造函数 */
test t2(t1);
}
int main(int argc, char const* argv[]) {
func();
return 0;
}
析构函数
析构函数主要进行资源的释放操作,如果类中没有需要手动释放的资源,可以保持空实现。