在C语言中,我们在写一些项目时难免会要进行各种初始化和空间清理,但是有时候也可能会忘记初始化或空间清理,就会导致一些问题。
struct my_vector
{
int *_a;
int _capacity;
int _size;
}
void InitVector(struct my_vector *p)
{
p->_a = (int*)malloc(sizeof(int)*4);
if (p->_a == NULL)
{
perror("malloc failed");
return;
}
p->_size = 0;
p->_capacity = 4;
}
void DestroyVector(struct my_vector *p)
{
assert(p);
free(p->_a);
p->_a=nullptr;
p->_capacity=p->_size=0;
}
每次都要初始化和清理较为繁琐,于是乎,C++提出了构造函数和析构函数,构造函数可以帮助我们完成初始化,而析构函数可以帮助我们进行空间清理。
1.构造函数
构造函数如何使用?
构造函数放在类里面,函数名与类名相同,无返回值。
class my_vector
{
int *_a;
int _capacity;
int _size;
public:
my_vector()
{
_a = (int*)malloc(sizeof(int)*4);
if (_a == NULL)
{
perror("malloc failed");
return;
}
_size = 0;
_capacity = 4;
}
}
也可以传缺省值
class my_vector
{
int *_a;
int _capacity;
int _size;
public:
my_vector(int n=4)
{
_a = (int*)malloc(sizeof(int)*n);
if (_a == NULL)
{
perror("malloc failed");
return;
}
_size = 0;
_capacity = n;
}
}
还能够成函数重载,但是无参调用存在歧义,不能同时存在,例如以下代码就存在二义性:
class my_vector
{
int *_a;
int _capacity;
int _size;
public:
my_vector(int n=4)
{
_a = (int*)malloc(sizeof(int)*n);
if (_a == NULL)
{
perror("malloc failed");
return;
}
_size = 0;
_capacity = n;
}
my_vector()
{
_a = (int*)malloc(sizeof(int)*4);
if (_a == NULL)
{
perror("malloc failed");
return;
}
_size = 0;
_capacity = 4;
}
}
所以在有构造函数的函数重载时,尽量要传不同类型和数量的参数,避免产生歧义
2.析构函数
析构函数像是构造函数的亲兄弟,如果说构造函数是头,那么析构函数就是尾巴,析构函数的使用只需在构造函数前面加上“~”符号,并在类的生命周期即将结束时调用此函数,可以说析构函数就是为清理空间而存在。
class my_vector
{
int *_a;
int _capacity;
int _size;
public:
my_vector(int n=4)
{
_a = (int*)malloc(sizeof(int)*n);
if (_a == NULL)
{
perror("malloc failed");
return;
}
_size = 0;
_capacity = n;
}
~my_vector()
{
free(_a);
_a=nullptr;
_size=_capacity=0;
}
但是,如果我们不写构造函数和析构函数编译器会不会自动生成呢?
答案是会的。
关于默认生成的构造/析构函数,编译器对内置类型成员不做处理,而自定义类型成员会去调用他的构造/析构函数。