由C++构造函数初始值列表想到的
2015-11-10 20:30
357 查看
引子
大家在编写C++代码的时候,总是会遇到下面这个问题,什么时候为构造函数提供初始值列表(当然,推荐做法都是以初始值列表代替构造函数体内赋值)。数据成员初始化动作是在构造函数体之前的,相对应的,析构函数的数据成员销毁动作是在析构函数体之后的。所常见的必须提供初始值列表的情况有,数据成员含有const成员变量
数据成员含有引用
前面两个比较好理解,const和引用都是必须在声明时赋初值的。但是数据成员中有自定义类型时,就要考虑自定义类型有没有默认构造函数了,例如下面代码:
class B{ public: int mem; B(int para) : mem(para) {} }; class A{ public: B mem_b; A(int para) { // 注意这种赋值有一个隐式操作 // mem_b = static_cast<B>(mem); // 或 // mem_b = temp(mem); // 然后再调用拷贝赋值运算符赋值给mem_b mem_b = mem; } };
上述代码编译是不会通过的,因为数据成员mem_b没有提供默认构造函数,所以在进入函数体赋值之前,是要报错的。注意,如果自定义类型没有提供拷贝赋值运算符,编译器会为其提供合成的拷贝赋值运算符执行简单内存拷贝操作。
但是为什么人们经常会忽视第三种情况呢,这是由于人们有个误区。
下意识将内置类型和自定义类型分开
其实自定义类型和内置类型说到底都是类型,都是描述数据在内存中的组织方式和对应的操作。这样说是不严谨的,编译原理中对数据类型的定义是,一组值得集合,以及对这组值进行的操作(运算)的集合。数据在计算机内存中无非是二进制位串的集合,本身没有任何意义,有意义的是如何对其进行解释。任何语言都有自定义类型,如果语言只有内置类型那么语言的易用性就会有很大折扣。自定义类型是由自定义类型和或者是内置类型的集合构成的,是由现有类型的笛卡尔积表示的。但是自定义类型是有前提的,就是不能存在递归情况,如下所示,
class A{ public: int mem; A mem_a; };
这种情况下,编译器对类型A的推导是不会终止的。所以C++规定自定义类型时,需要数据成员是完整类型。
自定义类型与内置类型没什么区别,都是一组值的集合和在这些值上的操作。只是这种类型的值域,以及其上的操作需要用户自己来控制,所以有许多情况需要用户注意。相对应的,类模版是构造自定义类型的模板,让用户在编写代码时能够动态定义用户类型。
相关文章推荐
- C++编程经验-返回局部变量的讨论
- c++primer第五版第十二章12.20习题用一个StrBlobPtr打印出StrBlob中的元素
- 操作系统中轮转法的模拟
- c++从入门到实践
- 题目1.2.4 The Seven Percent Solution(C++)
- Rational Rose 2003 逆向工程转换C++源代码成UML类图
- C语言学习——怪异的事情
- 在C语言中利用PCRE实现正则表达式
- 【c语言】 编写一个函数reverse_string(char * string)(递归实现)
- C++单链表实现冒泡排序
- C++中实数(以float为例)的存储方式
- C++链表翻转
- 黑马程序员--C语言基础--指针
- C++标准库中的list的实现原理
- 01-C++11的使用
- C语言基础-指针
- C++基础::类设计的几大原则
- C++中指针和引用的区别(超详细)
- C++内存管理学习堆和栈
- 【c语言】 模拟实现printf,要求功能: my_printf("dc\ts\ndc\ndc\ts!", ...)