目录
4. 合成的默认构造函数为内置类型的成员变量初始化的值不确定
5. =default形式的默认构造函数,也不能初始化为内置类型的成员变量初始化一个确定的值
《C++ primer》第五版中有讲:
有一条准则,即定义在块中的内置类型或复合类型(数组和指针)默认初始化后,对象的值是不确定的。这条准则同样也适用于默认构造函数,因此,成员变量是内置类型或者复合类型,这个时候,就需要自定义一个默认构造函数,否则,在创建类的对象后就会出现成员变量初始值未被定义的情况。
这一条准则,很耐人寻味,很多情况下,我们定义的类的成员变量很容易是内置变量或者复合类型。所以我们需要分清楚哪些类型是内置变量,哪些是复合变量。这对于这条准则的运用很重要。
| 类型 | 含义 | 最小尺寸(bit) |
|---|---|---|
| bool | 布尔类型 | - |
| char | 字符 | 8 |
| wchar_t | 宽字符 | 16 |
| char16_t | Unicode字符 | 16 |
| char32_t | Unicode字符 | 32 |
| short | 短整型 | 16 |
| int | 整型 | 16 |
| long | 长整型 | 32 |
| long long | 长整型 | 64 |
| float | 单精度浮点型 | 6位有效数字 |
| double | 双精度浮点型 | 10位有效数字 |
| long double | 扩展精度浮点型 | 10位有效数字 |
常见的有
指针
引用
为了便于理解,我们还是利用案例来说明情况
- //sales_data.h
- #ifndef SALES_DATA_H
- #define SALES_DATA_H
-
- #include
- #include
- using namespace std;
-
- class SalesData
- {
- public:
- void GetSaleBn()
- {
- cout << "sales_isbn:" << sale_isbn << endl;
- }
-
- private:
- int sale_isbn;
-
- };
-
- #endif
- //main.cpp
- #include "sales_data.h"
- #include
-
- int main()
- {
- std::cout << "SalesData totoal before..." << std::endl;
- SalesData total;
- total.GetSaleBn();
- std::cout << "SalesData totoal after..." << std::endl;
-
- return 0;
- }
编译方法使用以下Makefile:
- TGT:= main
- SRC:= $(wildcard *.cpp)
- OBJ:= $(patsubst %cpp,%o,$(SRC))
-
- CPPFLAGS := -I.
-
- all:$(TGT)
- >---@echo "Make successful [0]"
-
- $(TGT):$(OBJ)
- >---g++ $^ -o $@
-
- %.o:%.cpp
- >---g++ $(CPPFLAGS) $< -c
-
-
- clear:
- >---rm $(OBJ) $(TGT) log.log
- .PHONY: all clear
运行结果如下:
- goodstudy@xgoodstudyVPCEG27YC sales_data (study) $ ./main
- SalesData totoal before...
- sales_isbn:32764(值1)
- SalesData totoal after...
- xugoodstudyuegoodstudyCEG27YC sales_data (study) $ ./main
- SalesData totoal before...
- sales_isbn:32766(值2)
- SalesData totoal after...
- //如果不初始化,对象的内置变量成员值是不确定的,这样的程序是不健壮的,值得我们警惕。
sales_data.h文件内容如下
- #ifndef SALES_DATA_H
- #define SALES_DATA_H
-
- #include
- #include
- using namespace std;
-
- class SalesData
- {
- public:
- SalesData() = default;
- SalesData(int sale_a):sale_isbn(sale_a)
- {
- }
- void GetSaleBn()
- {
- cout << "sales_isbn:" << sale_isbn << endl;
- }
-
- private:
- int sale_isbn;
- };
-
- #endif
编译命令参考以上,编译后,编译生成目标文件 ./main
- xuehaiyang@xuehaiyang-VPCEG27YC sales_data (study) $ ./main
- SalesData totoal before...
- sales_isbn:32767(值1)
- SalesData totoal after...
- xuehaiyang@xuehaiyang-VPCEG27YC sales_data (study) $ ./main
- SalesData totoal before...
- sales_isbn:32764(值2)
- SalesData totoal after...
- xuehaiyang@xuehaiyang-VPCEG27YC sales_data (study) $ ./main
- SalesData totoal before...
- sales_isbn:32766(值3)
- SalesData totoal after...
- xuehaiyang@xuehaiyang-VPCEG27YC sales_data (study) $
运行结果显示,手动构造函数和合成的构造函数效果都一样,都不能初始化一个确定的值。
《C++ primer》第五版讲到,=default既可以声明在类的内部,也可以作为定义出现在类的外部。如果出现在类的内部,表明默认构造函数是内联的,如果出现在类的外部,则表明此构造函数不是内联的。接下来我们补充一个=default出现在类外部的案例
- #ifndef SALES_DATA_H
- #define SALES_DATA_H
-
- #include
- #include
- using namespace std;
-
- class SalesData
- {
- public:
- // SalesData() = default;
- SalesData();
- SalesData(int sale_a):sale_isbn(sale_a)
- {
- }
- void GetSaleBn()
- {
- cout << "sales_isbn:" << sale_isbn << endl;
- }
-
- private:
- int sale_isbn;
-
- };
-
- #endif
- //sales_data.cpp
- #include"sales_data.h"
- SalesData::SalesData() =default;
编译参考以上,结果如下
- xuehaiyang@xuehaiyang-VPCEG27YC sales_data (study) $ ./main
- SalesData totoal before...
- sales_isbn:32767(值1)
- SalesData totoal after...
- xuehaiyang@xuehaiyang-VPCEG27YC sales_data (study) $ ./main
- SalesData totoal before...
- sales_isbn:32764(值2)
- SalesData totoal after...
- xuehaiyang@xuehaiyang-VPCEG27YC sales_data (study) $ ./main
- SalesData totoal before...
- sales_isbn:32767(值3)
- SalesData totoal after...
结论文章开头说的一样。
如果想让上述案例成员变量的值是确定的,可以有多种方法,其中一种就是可以在定义内置成员变量时,就显式的给出确定的值,以下说明了这点。
- //sales_data.h
- #ifndef SALES_DATA_H
- #define SALES_DATA_H
-
- #include
- #include
- using namespace std;
-
- class SalesData
- {
- public:
- SalesData() = default;
- SalesData(int sale_a):sale_isbn(sale_a)
- {
- }
- void GetSaleBn()
- {
- cout << "sales_isbn:" << sale_isbn << endl;
- }
-
- private:
- int sale_isbn = 0;
-
- };
-
- #endif
main.cpp参考之前的案例,结果如下
- xuehaiyang@xuehaiyang-VPCEG27YC sales_data (study) $ ./main
- SalesData totoal before...
- sales_isbn:0
- SalesData totoal after...
《C++ primer》第五版