什么是默认构造函数
默认构造函数(default constructor)就是不带任何参数的构造函数。默认的构造函数用来创建一个“原型(vanilla)对象”,当编译器需要创建一个对象而又不知任何细节时,默认的构造函数就显得非常重要。
- 记住,一旦有了一个构造函数,编译器就会保证了不管什么情况下它总是会被调用。
1、我们不写编译默认生成那个构造函数,叫默认构造
2、无参构造函数也可以叫默认构造
3、全缺省也可以叫默认构造
可以不传参数就调用构造,都可以叫默认构造
这三个函数不能同时存在,只能存在一个
在类中没有构造函数的情况
默认构造函数非常重要,所以当(且仅当)在一个类(struct 或 class)中没有构造函数时,编译器就会自动为它创建一个。因此即使没有默认构造函数,程序照样可以正常运行,如下面例子:
class Stack
{
private:
int* _a;
int capacity;
int top;
};
int main()
{
Stack st;
return 0;
}
然而,一旦有操作数而没有默认构造函数,上面的例子就会产生一个编译错误。
大家可能会想,由编译器合成的构造函数应该可以做一些智能化的初始化工作,比如把内存置零。但事实并非如此。因为这样会增加额外的负担,而使程序无法控制。
如果想把内存初始化为0,那就得显式得编写默认的构造函数。
class Stack
{
public:
Stack(size_t capacity = 3)
{
_a = (int*)malloc(sizeof(int) * capacity);
if (nullptr == _a)
{
perror("malloc申请空间失败!");
}
_capacity = capacity;
_top = 0;
}
private:
int* _a;
int _capacity;
int _top;
};
int main()
{
Stack st;
return 0;
}
编译器默认生成的默认构造函数
内置类型成员不做处理,自定义类型会去调用他的默认构造
class Stack
{
public:
Stack(size_t capacity = 3)
{
cout << "Stack(size_t capacity = 3)" << endl;
_a = (int*)malloc(sizeof(int) * capacity);
if (nullptr == _a)
{
perror("malloc申请空间失败!");
}
_capacity = capacity;
_top = 0;
}
private:
int* _a;
int _capacity;
int _top;
};
//用两个栈实现一个队列
class MyQueue
{
Stack _pushst;
Stack _popst;
};
int main()
{
MyQueue mq;
return 0;
}
由上可以看出,这样可以调两次栈的构造函数实现初始化。
class MyQueue
{
// 默认生成的构造函数,啥事都干?
//处理自定义类型(会去调用成员的默认构造)
//内置类型不确定(看编译器),建议当成不处理
Stack _pushst;
Stack _popst;
int size;
};
看到上面这段代码,size在vs2022中也会被初始化为0,但是在vs2013中就不会。
标准规定:默认生成构造函数:内置类型成员不做处理,自定义类型会去调用他的默认构造。
尽管编译器会创建一个默认的构造函数,但是编译器所构造的函数的行为很少使期望的。我们应该把这个特征看成是一个安全网,尽量少使用它。一般来说,因该明确地定义自己的构造函数,而不让编译器来完成!
内置类型成员变量在类中声明时可以给默认值
注意:C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在类中声明时可以给默认值。
class Stack
{
private:
//C++11支持,声明的时候给缺省值。
int* _a = (int*)malloc(sizeof(int) * capacity);
int capacity = 1;
int top = 1;
};
int main()
{
Stack st;
return 0;
}