C++ primer第二章—变量和基本类型

2.1 基本内置类型

2.1.1 算术类型

C++ 标准规定了每个算术类型的最小存储空间,但它并不阻止编译器使用更大的存储空间

类型含义最小尺寸
bool布尔类型未定义
char字符8位
wchar_t宽字符16位
char16_tUnicode字符16位
char32_tUnicode字符32位
short短整型16位
int整形16位
long长整型32位
long long长整型64位
float单精度浮点数6位有效数字
double双精度浮点数10位有效数字
long double扩展精度服点数10位有效数字

带符号类型和无符号类型

  1. 当明确知道数值不可能为负数时,用无符号类型
  2. int执行整数运算,超过int表示范围的用long long
  3. 执行浮点数用double类型

2.1.2 类型转换

  1. 当赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数
  2. 当赋给有符号类型一个超出它表示范围的值时,结果是未定义的

2.1.3 字面值常量

数值20进制
20十进制
024八进制
0x14十六进制

字符串字面值

如果两个字符串字面值位置紧邻且仅有空格、缩进、换行符分隔,则它们实际上是一个整体。

2.2 变量

2.2.1 变量定义

  1. 初始化不是赋值:初始化的含义是创建变量时赋予其一个初始值,而赋值的含义是把对象的当前值擦除,而以一个新的值来代替
  2. 如果使用列表初始化且初始值存在丢失信息的风险,则编译器报错
  3. 定义于函数体内的内置类型的对象如果没有初始化,则其值未定义

2.2.2 变量声明和定义的关系

  1. 如果想声明一个变量而非定义它,就在变量名前添加关键字extern,而且不要显示地初始化变量
  2. 变量只能被定义一次,可以被多次声明
  3. 如果要在多个文件中使用同一个变量,就必须将定义和声明分开,变量的定义只能出现在一个文件中,其他用到该变量的文件必须对其进行声明,却不能重复定义

2.2.3 标识符

  1. 不能连续出现两个下划线,不能以下划线紧连大写字母开头

2.2.4 名字的作用域

  1. 作用域操作符::左侧为空时,即为全局作用域

2.3 复合类型

2.3.1 引用

引用为对象起了另外一个名字

  1. 引用非对象,引用是为一个已经存在的对象起的另外一个名字,由于引用不是一个对象,不能定义引用的引用

2.3.2 指针

  1. 指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象
  2. 指针无须定义时赋值,在块作用域(函数体)内定义的指针如果没有初始化,也将是不确定的值
  3. 取地址符&、解引用符*
  4. 建议初始化所有指针
  5. 赋值永远改变的是等号左侧的对象
  6. void* 指针可以存放任意对象的地址
  7. 指针类型必须要与所指对象严格匹配
int i = 42;
long *lp = &i;  // 错误:类型不匹配

2.3.3 理解复合类型的声明

  1. 在同一条定义语句中,可以定义不同类型的变量(但基本数据类型只有一个)
//i是一个int型的数,p是一个int型指针,r是一个int型引用
int i = 1024, *p = &i, &r = i;
  1. 指向指针的指针
  2. 指向指针的引用:不能定义指向引用的指针,因为引用不是一个对象,但是可以存在对指针的引用
int *p;
int *&r = p;    //r是一个对指针p的引用

2.4 const限定符

  1. 利用一个对象去初始化另外一个对象,则它们是不是const都无关紧要
  2. 如果想在多个文件之间共享const对象,必须在变量定义之前添加extern关键字

2.4.1 const的引用

const int ci = 1024;
const int &ri = ci; //注意必须加const
  1. 初始化常量引用允许任意表达式作为初始值
  2. 常量引用仅对引用可参与的操作做出了限定,对于引用本身是不是常量未作限定
  3. 非常量引用不能指向一个常量对象,但常量引用可以指向非常量对象
  4. 常量引用必须要初始化

2.4.2 指针与const

  1. 指向常量的指针与常量指针不同
  2. 指针本身是常量并不代表不能通过指针修改其所指向的对象的值,能否这样做完全依赖于其指向对象的类型。
  3. 常量对象的地址只能使用指向常量的指针来存放,但指向常量的指针可以存放非常量对象的地址
  4. 常量指针必须初始化,指向常量的指针不一定要初始化(这与常量引用不同)

2.4.3 顶层const

  1. 顶层 const 表示指针本身是个常量,底层 const(low-level const)表示指针所指的对象是一个常量。指针类型既可以是顶层 const 也可以是底层 const。
  2. 顶层 const 没有影响。拷贝操作不会改变被拷贝对象的值,因此拷入和拷出的对象是否是常量无关紧要。
int i = 0;
int *const p1 = &i;       // 不能改变p1的值,这是一个顶层const
const int ci = 42;        // 不能改变ci的值,这是一个顶层const
const int *p2 = &ci;      // 允许改变p2的值,这是一个底层const
const int *const p3 = p2; // 靠右的const是顶层const,靠左的是底层const
const int &r = ci;        // 用于声明引用的const都是底层const
i = ci;     // ok: 拷贝ci的值,ci是一个顶层const,对此操作无影响,注意是拷贝时可以,初始化时不可以
p2 = p3;    // ok: p2和p3指向的对象类型相同,p3顶层const的部分不影响
  1. 底层const的限制不能忽视。拷入和拷出的对象必须具有相同的底层 const 资格。或者两个对象的数据类型可以相互转换。一般来说,非常量可以转换成常量,反之则不行。
int *p = p3;    	// error: p3包含底层const的定义,而p没有
p2 = p3;        	// ok: p2和p3都是底层const
p2 = &i;        	// ok: int*能转换成const int*
int &r = ci;    	// error: 普通的int&不能绑定到int常量上
const int &r2 = i;  // ok: const int&可以绑定到一个普通int上

2.4.4 constexpr和常量表达式

  1. C++11允许将变量声明为constexpr类型以便由编译器来验证变量的值是否是一个常量表达式。
  2. 指针和引用都能定义成 constexpr,但是初始值受到严格限制。constexpr 指针的初始值必须是0、nullptr 或者是存储在某个固定地址中的对象。函数体内定义的普通变量一般并非存放在固定地址中,因此 constexpr 指针不能指向这样的变量。相反,函数体外定义的变量地址固定不变,可以用来初始化 constexpr 指针。
  3. 在 constexpr 声明中如果定义了一个指针,限定符 constexpr 仅对指针本身有效,与指针所指的对象无关。
const int *p = nullptr; 	 // p是一个指向整型常量的指针
constexpr int *q = nullptr;  // q是一个指向整数的常量指针
  1. 与其他常量指针类似, constexpr 指针既可以指向常量也可以指向一个非常量

2.5 处理类型

2.5.1 类型别名

  1. 使用关键字 typedef 定义类型别名。
typedef double wages;   // wages是double的同义词
typedef wages base, *p; // base是double的同义词,p是double*的同义词
  1. 使用关键字 using 进行别名声明,作用是把等号左侧的名字规定成等号右侧类型的别名
using SI = Sales_item; // SI是Sales item的同义词

2.5.2 auto类型说明符

  1. auto 类型说明符,能让编译器自动分析表达式所属的类型。auto 定义的变量必须有初始值
  2. 使用 auto 也能在一条语句中声明多个变量。因为一条声明语句只能有一个基本数据类型,所以该语句中所有变量的初始基本数据类型都必须一样
  3. auto 一般会忽略顶层 const,同时底层 const 则会保留下来
  4. 设置类型为 auto 的引用时,原来的初始化规则仍然适用,初始值中的顶层常量属性仍然保留。
auto &g = ci;   		// g是一个整型常量引用,绑定到ci
auto &h = 42;   		// error: 不能为非常量引用绑定字面值
const auto &j = 42;     // ok: 可以为常量引用绑定字面值
const auto f = ci;    // ci是int类型,f是const int类型
  1. 注意auto是根据=号右边的数据类型推断=号左边的数据类型

2.5.3 decltype类型指示符

  1. decltype 类型指示符,作用是选择并返回操作数的数据类型,此过程中编译器不实际计算表达式的值。
  2. decltype 处理顶层 const 和引用的方式与 auto 有些不同,如果 decltype 使用的表达式是一个变量,则 decltype 返回该变量的类型
  3. decltype 和 auto 的另一处重要区别是,decltype 的结果类型与表达式形式密切相关。注意:如果 decltype 使用的是一个不加括号的变量,则得到的结果就是该变量的类型;如果给变量加上了一层或多层括号,则 decltype 会得到引用类型,因为变量是一种可以作为赋值语句左值的特殊表达式。
// decltype的表达式如果是加上了括号的变量,结果将是引用
decltype ((i)) d;  // 错误:d是int&,必须初始化
decltype (i) e;    // 正确:e是一个(未初始化的)int
decltype(*p) c; // *p是int型,而c是int&类型
  1. decltype((var)) 的结果永远是引用,而 decltype(var) 的结果只有当 var 本身是一个引用时才会是引用。
  2. 赋值是会产生引用的一类典型表达式,引用的类型就是左值的类型。也就是说,如果 i 是 int,则表达式 i=x 的类型是 int&
int a = 3, b = 4;
decltype(a) c = a;
decltype(a = b) d = a;  // 注意d是int&类型

2.6 自定义数据结构

  1. C++11 规定可以为类的数据成员(data member)提供一个类内初始值(in-class initializer)。创建对象时,类内初始值将用于初始化数据成员,没有初始值的成员将被默认初始化。
  2. 类定义的最后应该加上分号。
  3. 头文件(header file)通常包含那些只能被定义一次的实体,如类、const和constexpr变量。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值