Ch1开始
略
这一章包含控制流,条件,循环,注释,标准IO等内容。
对于C语言/ACM C+STL中常见数值的内容不再赘述,仅总结较为不熟悉的内容。
Part I C++基础
CH2 变量和基本类型
2.1 基本内置类型
2.1.1 算术类型
2.1.1 类型转换
- 向unsigned赋超出范围的值,结果取余,对于signed,结果未定义。
- 不要混用signed和unsigned。表达式中既有signed又有unsigned,当signed为负值时会出现异常结果,因为它会自动转换为unsigned。
2.1.3 字面值常量
-
整型字面值:
- 默认情况下,十进制为带符号数(int, long, long long),八进制和十六进制则都有可能(前三种加上uint,ull)。
- 类型是能够容纳该数的有关类型中尺寸最小者,若超过所有类型的表示范围将发生错误。
- short没有对应的字面值。
- 十进制字面值中不含负号,负号的作用是取负值。
-
字符串字面值:
- 实质是常量字符构成的数组
- 编译器在末尾自动添加空字符'\0',因此实际长度比内容多1
-
转义序列
-
通过前后缀指定字面值类型
-
其他字面值: true false nullptr
2.2 变量
2.2.1 变量定义
- 列表初始化,使用花括号。列表初始化如果存在丢失信息的风险,则编译器会报错。
- 默认初始化:函数体外为0,函数体内为未定义。
2.2.2 变量定义与声明的关系
声明:使得名字为程序所知
定义:创建与名字关联的实体
分离式编译:详见2.6.3和6.1.3
extern int i; //声明
int j; //声明并定义
2.2.3 标识符
2.2.4 名字的作用域
2.3 复合类型
2.3.1 引用
- 引用即别名,本身不是一个对象。
- 定义时必须初始化,初始值不能是字面值,应该是对象,且引用类型与被引用对象的类型一致。
2.3.2 指针
- 指针本身是一个对象,也无须定义时初始化。
- 使用解引用符(*)来操作对象。
- 不能把int变量直接赋值给指针,即便值为0。
- 建议初始化所有指针。
- void*指针
- 特殊指针类型,可存放任意对象的地址
- 只能与其他指针比较,作为函数的输入输出,或者赋值给另一个void*指针
- 不能直接操作void*指向的对象
- 指向指针的引用
int i = 42;
int *p;
int *&r = p; //从右向左阅读,r表示指向指针的引用
r = &i; //等价于p = &i
*r = 0; //等价于*p = 0
2.4 const 限定符
初始化和const
- 默认状态下,const对象尽在当前文件内有效
- 编译器在用到const变量处执行替换
- 如要在多个文件之间共享const对象,必须在定义前加extern关键字
2.4.1 const的引用
-
只能用对常量的引用来引用常量(引用的类型与所引用对象保持一致)
-
引用的类型与所引用对象保持一致,但存在例外情况:初始化常量引用时允许用任意表达式作为初始值,如字面值和非常量,只要该表达式能够转换成引用的类型即可。
int i = 42; const int &r1 = i; //ok const int &r2 = 42; //ok const int &r3 = r1 * 2; //ok int &r4 = r1 * 2; //wrong,非常量引用不能这么做
实质上,此时编译器创建了一个对应类型的临时量,该临时量被常量引用绑定。
常量引用仅对引用可参与的操作进行了限定,它可以引用非常量,但不能通过引用修改非常量的值。
2.4.2 指针和const
指针可以指向常量或非常量,指向常量的指针不能用于修改所指对象的值。
指针类型必须与其所指对象类型一直,但存在例外情况:允许一个指向常量的指针,指向一个非常量对象。利用与2.4.1相似。总得来说,可以认为const类型的指针和引用自认为指向了常量,自觉地不去改变所指对象的值。
const指针
由于指针本身是一个对象,允许把指针本身定为常量。
int errNumb = 0;
int *const curErr = &errNumb; // 指向非常量的常量指针。可以通过curErr修改errNumb
const double pi = 3.14;
const double *const pip = π //指向常量的常量指针。
//从右向左阅读,表示pip是常量对象,且为指针。该指针指向的对象为const double。
2.4.3 顶层const
顶层const表示指针本身是常量(更一般的,表示任意对象本身是常量),底层const表示所指对象是常量(与指针、引用等复合类型的基本类型有关)。
当执行对象的拷贝操作时,顶层const通常不受影响,而底层const却不能忽视要求拷入和拷出对象具有相同的底层const资格,或者数据类型能够转换。一般来说,非常量可以转换成常量,反之则不行。
2.4.4 constexpr 和 常量表达式
常量表达式
指在编译期间就得到计算结果的表达式。
const int N = 114514; // yes
const int M = N + 1; // yes
int P = 998244353; // no,因为类型是非常量
const int sz = size(); //no,因为编译期无法获取
constexpr
C++ 11 规定,允许将变量声明为constexpr类型以由编译器验证变量的值是否为常量表达式。
constexpr const int sz = size(); //只有当size()是constexpr函数时才正确
6.5.2节将深入介绍constexpr函数。
如果你认定一个表达式是常量表达式,就声明为constexpr。
字面值类型
容易得到值的类型。如算术类型,引用,指针。
非字面值类型:自定义类,IO库,string类型等。
指针和引用能够定义为constexpr,但初始值受严格限制。
指针和constexpr
constexpr把它所定义的对象置为了顶层const,与指针所指的对象无关
2.5 处理类型
2.5.1 类型别名
传统方法 typedef
typedef double wages;
typedef wages base, *p; //base是double的别名,p是*double的别名
新标准 别名声明
using SI = Sales_item;
2.5.2 auto类型说明符
-
因为一条声明语句中只能有一个基本数据类型,因此该语句中所有变量初始基本数据类型必须一样。
auto i = 0, *p = &i; //ok,相当于int i = 0, *p = &i; auto sz = 0, pi = 3.14; //wrong
-
auto一般会忽略顶层const,而底层const被保留
const int ci = i, &cr = ci; auto b = ci; //b为int auto c = cr; //c为int auto d = &i; //d为int* auto e = &ci; //e为(const int)*
如果希望推断出的auto类型是顶层const,需要明确指出
const auto f = ci; //ci的推演类型为int,f为const int
还可以将引用类型设置为auto,这时原来的初始化规则仍适用
auto &g = ci; //ok auto &h = 42; //wrong, 非常量引用不能绑定字面值 const auto &j = 42; //ok,常量引用可以绑定字面值
2.5.3 decltype类型指示符
对于需要根据表达式推断类型,而不用该表达式初始化变量的情况,C++11引入了第二种类型说明符decltype
decltype(f()) sum = x; //sum的类型为f的返回类型
const int ci = 0, &cj = ci;
decltype(ci) x = 0; // const int x = 0;
decltype(cj) y = x; // const int &y = x;
decltype(cj) y; //错误,引用必须初始化
decltype与引用
有些时候表达式将向decltype返回引用。这种表达式通常可以作为一条复制语句的左值。
int i = 42, *p = &i, &r = i;
decltype(r + 0) b; //b是未初始化的int,因为r+0的结果是int型值
decltype(*p) c; //错误,c是int&,必须初始化
如*p, 表达式的内容是解引用操作,decltype的结果为int&。
与auto不同,decltype的结果形式与表达式形式密切相关,例如,当表达式被括号括起时,decltype的结果将为引用。
decltype((i)) d; //错误,d是int&,必须初始化
decltype(i) e; //正确,e是未初始化的int。
decltype((表达式))的结果永远为引用。当且仅当表达式结果为引用时,decltype(表达式)的结果为引用。
2.6 自定义数据结构
略。
预处理器概述
预处理器看到#include 标记时,用指定头文件的内容代替#include
此外,还有头文件保护符:
'#define' 把一个名字设置为预处理变量
'#ifdef' 当且仅当变量已定义时为真
'#ifndef' 当且仅当变量为定义时为真
一旦检查结果为真,则执行后续操作,直至遇到#endif为止。
使用这些功能能够有效防止重复包含的情况发生,因此最好习惯性地设置保护符,不管该文件是否被其他文件包含。
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
struct Sales_data {
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
}
#endif
预处理变量无视C++语言中关于作用域的规则。
标签:const,常量,int,PartI,C++,引用,类型,Primer,指针 From: https://www.cnblogs.com/vv123/p/18007107