目录一、引入二、初始化的概念区分三、语法格式及使用四、注意事项【⭐】五、总结与提炼一、引入 我们知道,对于下面这个类A的成员变量_a1和_a2属于【声明】,还没有在内存中为其开辟出一
_a1
和_a2
属于【声明】,还没有在内存中为其开辟出一块空间以供存放,真正开出空间则是在【定义】的时候,那何时定义呢?也就是使用这个类A去实例化出对象的时候class A {
public:
int _a1; //声明
int _a2;
};
int main(void)
{
A aa; // 对象整体的定义,每个成员什么时候定义?
return 0;
}
如果现在我在类A中加上一个const成员变量的话,初始化的时候似乎就出现了问题
const int _x;
const
修饰的变量有哪些特点const int i;
const
进行修饰的,不过编译后报出了错误说【必须初始化常量对象】,因为对于const
修饰的变量在声明的时候是必须要去进行初始化的,也就是要给到一个值现在我们就可以来聊聊有关上面的成员变量
_x
为什么没有被初始化的原因了👇
_a1
、_a2
、_x
都属于内置类型的数据,所以编译器不会理睬,可是呢const
修饰的变量又必须要初始化,这个时候该怎么办呢╮(╯▽╰)╭💬有同学说:这还不简单,给个缺省值不就好了
这位同学说的不错,这个办法确实是可以解决我们现在的问题,因为c++11里面为内置类型不初始化打了一个补丁,在声明的位置给到一个初始化值,就可以很好地防止编译器不处理的问题
但是现在我想问一个问题:如果不使用这个办法呢?你有其他方法吗?难道C++11以前就那它没办法了吗?
底下的同学确实想不出什么很好的解决办法,于是这个时候就要使用到本模块要学习的【初始化列表】了
概念:在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。
class Date
{
public:
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
【初始化列表】:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式
class Date
{
public:
Date(int year, int month, int day)
:_year(year)
, _month(month)
, _day(day)
{}
private:
int _year;
int _month;
int _day;
};
int main(void)
{
Date d(2023, 3, 30);
return 0;
}
可以通过调试来观察一下它到底是怎么走的
接下去我再来说说这一块的难点所在,准备好头脑风暴🌊
_a1
和_a2
我给到了缺省值,写了初始化列表后,它们还会被初始化吗?class A {
public:
A()
:_x(1)
{}
private:
int _a1 = 1; //声明
int _a2 = 1;
const int _x;
};
也通过调试来看一下
_a1
和_a2
的初始化,还是会通过给到的默认缺省值去进行一个初始化。根据上面所学,我给出以下的结论好,接下去难度升级,请问初始化列表修改成这样后三个成员变量初始化后的结果会是什么呢? 会是1、2、1吗?
class A {
public:
A()
:_x(1)
,_a2(1)
{}
private:
int _a1 = 1; //声明
int _a2 = 2;
const int _x;
};
一样通过调试来看看
_a2
了,因为我在声明的时候给到了缺省值,然后初始化列表去进行定义的时候又去进行了一次初始化,最后的结果以初始化列表的方式为主这里要明确的一个概念是,缺省参数只是一个备份,若是我们没有去给到值初始化的话,编译器就会使用这个初始值,若是我们自己给到了明确的值的话,不会去使用这个缺省值了【如果不清楚看看C++缺省参数】
接下去难度继续升级,请问下面这样初始化后的结果是多少?
_a1
和_a2
进行了++和- -,那此时会有什么变化呢?class A {
public:
A()
:_x(1)
,_a2(1)
{
_a1++;
_a2--;
}
private:
int _a1 = 1; //声明
int _a2 = 2;
const int _x;
};
如果对于上面的原理搞清楚了,那看这个就相当于是再巩固了一遍。也是一样,无论是否给到缺省值都会去初始化列表走一遍,若是构造函数内部有语句的话就会执行
清楚了初始化列表该如何使用,接下去我们来说说其相关的注意事项
const成员变量
const
修饰的成员变量和构造函数对于内置类型不做处理产生了一个冲突,因此祖师爷就提出了【初始化列表】这个概念引用成员变量
_z
需要被初始化,它必须要引用一个值没有默认构造的自定义类型成员(写了有参构造编译器就不会提供默认构造)
_b
class B {
public:
B()
:_b(0)
{}
private:
int _b;
};
class A {
public:
A()
:_x(1)
,_a1(3)
,_a2(1)
,_z(_a1)
{
_a1++;
_a2--;
}
private:
int _a1 = 1; //声明
int _a2 = 2;
const int _x;
int& _z;
B _bb;
};
💬那对于有参构造该如何去初始化呢?
还是可以利用到我们的【初始化列表】
通过调试来看看编译器是如何走的
看完了上面这一种,我们再来看看稍微复杂一些的自定义类型是否也遵循这个规则
typedef int DataType;
class Stack
{
public:
Stack(size_t capacity = 10) //全缺省构造
{
cout << "Stack()构造函数调用" << endl;
_array = (DataType*)malloc(capacity * sizeof(DataType));
if (nullptr == _array)
{
perror("malloc申请空间失败");
return;
}
_size = 0;
_capacity = capacity;
}
//....
private:
DataType* _array;
size_t _size;
size_t _capacity;
};
class MyQueue{
public:
//默认生成构造函数
private:
Stack _pushST;
Stack _popST;
size_t _t = 1;
};
int main(void)
{
MyQueue MQ;
return 0;
}
可能读者有所忘却,我们再通过调试来看一下
Stack(size_t capacity)
_t
,依旧会使用我给到的初始值1MyQueue()
:_pushST(10)
,_popST(10)
{}
可以通过调试再来看看
//无参构造MyQueue(){<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->}
所以可以看出,对于【内置类型】不做处理,【自定义类型】会调用它的默认构造可以看出其实就是当前类构造函数的初始化列表在起作用
在看了MyQueue类各种初始化列表的方式后,其实也可以总结出一点,无论如何不管有没有给到缺省值,只要是显式地写了一个构造函数,就可以通过调试去看出编译器都会通过【初始化列表】去进行一个初始化
class A
{
public:
A(int a)
:_a1(a)
,_a2(_a1)
{}
void Print() {
cout<<_a1<<" "<<_a2<<endl;
}
private:
int _a2;
int _a1;
};
int main() {
A aa(1);
aa.Print();
}
但结果却和我们想象的不一样,_a1
是1,_a2
却是一个随机值,这是为什么呢?
_a2
再去初始化的_a1
,对于【内置类型】我们可以知道是编译器是不会去进行初始化的,那若是一开始使用_a1
去初始化_a2
的时候,那_a2
就会是一个随机值,但是_a1
却使用传入进来的形参a进行了初始化,那它的值就是1_a1
先进行初始化即可,就不会造成随机值的现象了现在你在翻上去把所有的调试图一幅幅看下来就可以发现出初始化列表是存在顺序的,它的顺序不是在列表中谁先谁后的顺序,而是类的成员变量声明的顺序
最后来总结一下本文所学习的内容📖
面对必须在声明时期初始化的成员函数,我们引入了初始化列表这个东西,知道了祖师爷在构造函数中还做了这么个小文章😄。有了它,我们就再也不用担心成员变量不会被初始化的问题了,无论是你是否给到缺省值,编译器都会去走一遍构造函数的初始化列表,若是没有在定义处给到初始值,就会采用缺省值;若是给到了初始值就会采用这个值
不仅如此,初始化列表还有很多的注意事项:
const
修饰的成员变量、引用类型成员、无默认构造函数的自定义成员变量初始化列表是构造函数这一块的难点,也是祖师爷面对C++某些地方缺陷设计出来的,搞懂之后就会豁然开朗了
以上就是C++之谈谈构造函数的初始化列表的详细内容,更多关于C++构造函数的资料请关注编程网其它相关文章!
--结束END--
本文标题: C++之谈谈构造函数的初始化列表
本文链接: https://lsjlt.com/news/208455.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0