简介

C++数据类型包括基本内置类型、复合类型和自定义数据结构。

  • 基本内置类型:编译器内置的基本类型,包括算数类型(字符、整型数、布尔值、浮点数)和空类型void
  • 复合类型:基于其他类型定义的类型,包括数组、C风格字符串、指针、引用、C风格结构体(POD)和联合体(Union)
  • 自定义数据结构:用struct或者class定义的类

POD:Plain Old Data,用来表明C中和C相兼容的数据类型,在C中可以用is_pod<T>::value判断是否是POD类型。

内置类型

Tips:C++中整型大小因编译器和操作系统的不同而不同,通常人们假定short是16位,int是32位,long是32位,long long是64位。

实际开发中我们仅使用C++内置整型中的int,如果程序中需要大小不同的整型,那么:

  • 在合适情况下,推荐用size_tptrdiff_t
  • 我们可以认为int至少32位,如果需要使用64位整数,那么使用int64_t
  • 不要使用uint32_t等无符号类型,你应该使用断言来指出变量为非负数,混用有符号类型和无符号类型可能导致非预期的结果(见下文)

执行浮点数运算时使用double,因为float通常精度不够且双精度浮点数和单精度浮点数的计算代码相差无几

类型 类型名 占字节数 数值范围
整型 int(signed int) 4 1.2 数据类型 - 图1#card=math&code=-2147483648%20%5Csim%20%2B2147483647%20%28-2%5E%7B31%7D%20%5Csim%202%5E%7B31%7D-1%29&id=yZhye)
无符号整型 unsigned (unsigned int) 4 1.2 数据类型 - 图2#card=math&code=0%20%5Csim%204294967295%280%20%5Csim%202%5E%7B32%7D-1%29&id=D3c6R)
短整型 short(signed short) 2 1.2 数据类型 - 图3#card=math&code=-32768%20%5Csim%20%2B32767%28-2%5E%7B15%7D%20%5Csim%202%5E%7B15%7D-1%29&id=ttIPc)
无符号短整型 unsigned short 2 1.2 数据类型 - 图4#card=math&code=0%20%5Csim%2065535%280%20%5Csim%202%5E%7B16%7D-1%29&id=Rt9En)
长整型 long (signed long) 4 1.2 数据类型 - 图5#card=math&code=-2147483648%20%5Csim%20%2B2147483647%28-2%5E%7B31%7D%20%5Csim%202%5E%7B31%7D-1%29&id=QrF4Z)
无符号长整型 unsigned long 4 1.2 数据类型 - 图6#card=math&code=0%20%5Csim%204294967295%280%20%5Csim%202%5E%7B32%7D-1%29&id=bQ0pr)
双长型 long long 8 1.2 数据类型 - 图7#card=math&code=-9223372036854775808%20%5Csim%209223372036854775807%28-2%5E%7B63%7D%20%5Csim%202%5E%7B63%7D-1%29&id=WUuSy)
字符型 char 1 1.2 数据类型 - 图8#card=math&code=-128%20%5Csim%20%2B127%28-2%5E7%20%5Csim%202%5E7-1%29&id=GuzO1)
无符号字符型 unsigned char 1 1.2 数据类型 - 图9#card=math&code=0%20%5Csim%20255%280%20%5Csim%202%5E8-1%29&id=h6c7A)
单精度型 float 4 1.2 数据类型 - 图10
双精度浮点型 double 8 1.2 数据类型 - 图11
长双精度浮点型 long double 8 1.2 数据类型 - 图12
布尔型 bool 1 true, false
空类型 void

字节byte:可寻址的最小内存块,大多数机器的字节由8比特构成

以我所在的64位机器为例:

  1. #include <iostream>
  2. int main() {
  3. std::cout << "size of int:" << sizeof(int) << std::endl;
  4. std::cout << "size of unsigned:" << sizeof(unsigned) << std::endl;
  5. std::cout << "size of short:" << sizeof(short) << std::endl;
  6. std::cout << "size of unsigned short:" << sizeof(unsigned short) << std::endl;
  7. std::cout << "size of long:" << sizeof(long) << std::endl;
  8. std::cout << "size of unsigned long:" << sizeof(unsigned long) << std::endl;
  9. std::cout << "size of long long:" << sizeof(long long) << std::endl;
  10. std::cout << "size of char:" << sizeof(char) << std::endl;
  11. std::cout << "size of unsigned char:" << sizeof(unsigned char) << std::endl;
  12. std::cout << "size of float:" << sizeof(float) << std::endl;
  13. std::cout << "size of double:" << sizeof(double) << std::endl;
  14. std::cout << "size of long double:" << sizeof(long double) << std::endl;
  15. std::cout << "size of bool:" << sizeof(bool) << std::endl;
  16. }
  17. // 输出:
  18. size of int:4
  19. size of unsigned:4
  20. size of short:2
  21. size of unsigned short:2
  22. size of long:8
  23. size of unsigned long:8
  24. size of long long:8
  25. size of char:1
  26. size of unsigned char:1
  27. size of float:4
  28. size of double:8
  29. size of long double:16
  30. size of bool:1

字面值常量literal

1. 整形和浮点型字面量

以0开头的整数表示八进制,以0x或者0X开头的整数表示十六进制,我们可以用下面三种方式表示20:

  1. 20 // 十进制
  2. 024 // 八进制
  3. 0x14 // 十六进制

浮点型字面量是一个double,其中指数部分用E或者e标识:

  1. 3.14159
  2. 3.14159E0
  3. 0.
  4. 0e0
  5. .001

2. 字符和字符串字面量

'a'表示一个字符;"a"字符串字面量包含字母a和空字符\0。当书写的字符串字面量比较长,我们可以采取分开书写的方式:

  1. std::cout << "line one"
  2. "line two" << std::endl;

3. 布尔字面量与指针字面量

  • truefalse和布尔类型的字面量
  • nullptr是指针类型的字面量

引用

C++11新增了右值引用的概念,我们这里只提及左值引用。

1. 引用概念

引用为对象起了另一个名字,定义引用时程序把引用和它的初始值绑定在一起,一旦初始化完成引用将一直和它的初始值对象绑定在一起。

  • 因为无法令引用重新绑定到另一个对象,因此引用必须初始化
  • 因为引用不是一个对象,所以不能定义引用的引用

2. 使用引用的原因

  • 引用类型可以避免对元素拷贝
  • 引用类型可以修改元素(如果仅仅是为了避免拷贝可以使用常量引用)

指针

指针是指向(point to)另外一种类型的复合类型。

1. 操作符&与*

获取对象地址时可以用&取地址符,利用指针访问对象时可以用*解引用符。

  1. int iVal = 42;
  2. int *p = &iVal; // p是指向iVal变量的指针
  3. cout << *p; // 解引用获得p指向的对象

2. 空指针

Tips:建议初始化所有指针,不清楚指向何处时初始化为nullptr

使用未经初始化的指针是引发运行时错误的一大原因,如果使用了未经初始化的指针,那么指针所占空间的当前内容将被当成一个地址值,当这个地址值指向的内存空间中正好有内容时,就可能引发难以预料的后果。实际开发过程中,我们尽量等定义了对象之后再定义指向它的指针,如果实在不清楚指针应该指向何处,那么将它初始化为nullptr,这样程序就能检测并指导它有没有指向任何具体的对象了。

C++11中我们可以用字面量nullptr初始化指针来得到空指针,它可以被转化成任意其他的指针类型。

3. void*

Tips:由于我们不知道void*指针指向什么类型的对象,因此不能直接操作它所指向的对象。

void*是一种特殊的指针类型,可以存放任意对象的地址,一般只能做如下操作:

  • void*指针和别的指针比较
  • 作为函数的输入输出
  • 赋值给另一个void*指针

自定义数据结构

C++允许用户以类的形式自定义数据类型,关于类的知识我们主要在后面的面向对象编程中讲解,这里简单给出一个例子:

  1. // C++11支持为数据成员提供一个类内初始值, 没有初始值的成员将被默认初始化
  2. struct bar {
  3. std::string name;
  4. int foo = 0;
  5. };