初始化
1 |
|
作用域
1 |
|
复合类型
引用
1 | int a, b, c, &ref; |
其中 int 是 BaseType,a, b, c, &ref 是 declarators
Declaration 就是一个 Base Type 后接上一些 declarators
1 |
|
声明引用时必须初始化,后续无法改变引用指向的对象
引用就是一个对象的别名,对引用的操作,就相当于操作引用关联的对象
指针
Unlike a reference, a pointer is an object in its own right.
A pointer holds the address of another object.
1 | int ival = 42; |
&
is the address-of operator.
Pointer values
The value stored in a pointer can be in one of four states:
- It can point to an object
- It can point to the location just immediately past the end of an object
- It can be a null pointer, indicating that it is not bound to any object
- It can be invalid; values other than the preceding three are invalid
Null Pointers
A null pointer doesn’t point to any object.
1 | int *p1 = nullptr; |
一些指针操作:
1 | int i = 42; |
1 | int *pi = 0; // pi is a valid, null pointer |
放在条件判断中的指针必须是合法的,因为条件判断表达式要用到指针的值
const 关键字
The compiler will usually replace uses of the variable with its corresponding value during compilation.
对于使用的常量,编译器在编译阶段将那些常量替换成实际内容。
To substitute the value for the variable, the compiler has to see the variable’s initializer. When we split a program into multiple files, every file that uses the const must have access to its initializer. In order to see the initializer, the variable must be defined in every file that wants to use the variable’s value (§ 2.2.2, p. 45).
为了能替换这些常量为实际内容,编译器必须能访问常量的 initializer。当程序分成多个文件时,每个文件中使用常量,必须能访问到这个常量的 initializer,所以这个常量需要在每个文件中都定义一遍。
To support this usage, yet avoid multiple definitions of the same variable, const variables are defined as local to the file. When we define a const with the same name in multiple files, it is as if we had written definitions for separate variables in each file.
默认情况下,常量是文件局部作用域。即使在每个文件中定义相同名字的常量,就好像我们分别写了许多不同变量的定义。
实际测试来看,如果在一个文件定义一个常量 a,在另一个文件引入前一个文件,再定义一个常量 a,编译时会报错。
To define a single instance of a const variable, we use the keyword extern
on both its definition and declaration(s):
1 | // file1.cpp |
Reference to const
We can bind a reference to an object of a const type.
A reference to const cannot be used to change the object to which the reference is bound:
1 | const int a = 1; |
Initialization and References to const
We can initialize a reference to const from any expression that can be converted to the type of the reference. In particular, we can bind a reference to const to a nonconst object.
1 | int i = 42; |
Pointers and const
1 | const double pi = 3.14; |
References and pointers to const,它们认为自己引用或指向的对象是常量的。
const Pointers
1 | const double pi = 3.14; |
Dealing with Types
Type Aliases
1 | typedef char *pstring; |
其中 const pstring cstr = 0;
等价于 char *const cstr = 0;
一种错误的解读方式是直接将 typedef 定义的类型直接带入,得到 const char *cstr = 0;
An alias declaration starts with the keyword using followed by the alias name and an =.
1 | using SI = Sales_item; // SI is a synonym for Sales_item |
The auto Type Specifier
we can let the compiler figure out the type for us by using the auto
type specifier.
auto
推断出来的类型,会丢弃 top-level const,使用引用对象原本的类型
1 | const int ci = i, &cr = ci; |
如果需要 top-level const,需要显示指定 const auto
不能用一个 auto 初始化多个不同类型的变量
Because a declaration can involve only a single base type, the initializers for all the variables in the declaration must have types that are consistent with each other:
1 | auto a = 1, b = 3.14; |
我们也可以要求返回一个引用:
1 | auto &g = ci; // g is a const int& that is bound to ci |
The decltype Type Specifier
有时候希望用一个表达式返回值的类型来定义一个变量,但又不想计算那个表达式,就可以用 decltype
。
1 | decltype(f()) sum = x; |
When the expression to which we apply decltype is a variable, decltype returns the type of that variable, including top-level const and references:
1 | const int ci = 0, &cj = ci; |
Defining Our Own Data Structures
定义属于自己的结构。
定义一个结构体,注意末尾的分号:
1 | struct Sales_data { |
定义一个结构体,并立刻创建定义对象:
1 | struct Sales_data { /* ... */ } accum, trans, *salesptr; |
编写头文件
当预处理器看到 #include
时,会将 #include
替换成相应文件的实际内容。
header guards 用于防止一个头文件被多次引用,导致问题。
1 |
|
预处理器变量必须整个程序内唯一。