|
40 | 40 | - 使用空格连接,继承自C。
|
41 | 41 | - 字符字面值:单引号, `'a'`
|
42 | 42 | - 字符串字面值:双引号, `"Hello World""`
|
| 43 | + - 分多行书写字符串。 |
| 44 | + ``` |
| 45 | + std:cout<<"wow, a really, really long string" |
| 46 | + "literal that spans two lines" <<std::endl; |
| 47 | + ``` |
43 | 48 | - 转义序列。`\n`、`\t`等。
|
44 | 49 | - 布尔字面值。`true`,`false`。
|
45 | 50 | - 指针字面值。`nullptr`
|
46 | 51 |
|
| 52 | +> 字符串型实际上时常量字符构成的数组,结尾处以`'\0'`结束,所以字符串类型实际上长度比内容多1。 |
| 53 | +
|
47 | 54 | ## 变量
|
48 | 55 |
|
49 | 56 | **变量**提供一个**具名**的、可供程序操作的存储空间。 `C++`中**变量**和**对象**一般可以互换使用。
|
|
56 | 63 | - 初始化 = 创建变量 + 赋予初始值
|
57 | 64 | - 赋值 = 擦除对象的当前值 + 用新值代替
|
58 | 65 | - **列表初始化**:使用花括号`{}`,如`int units_sold{0};`
|
59 |
| - - 默认初始化:定义时没有指定初始值会被默认初始化;在函数体内部的内置类型变量将不会被初始化。 |
| 66 | + - 默认初始化:定义时没有指定初始值会被默认初始化;**在函数体内部的内置类型变量将不会被初始化**。 |
60 | 67 | - 建议初始化每一个内置类型的变量。
|
61 | 68 |
|
62 | 69 | ### 变量的**声明**(declaration) vs **定义**(define)
|
63 | 70 | - 为了支持分离式编译,`C++`将声明和定义区分开。**声明**使得名字为程序所知。**定义**负责创建与名字关联的实体。
|
64 | 71 | - **extern**:只是说明变量定义在其他地方。
|
65 | 72 | - 只声明而不定义: 在变量名前添加关键字 `extern`,如`extern int i;`。但如果包含了初始值,就变成了定义:`extern double pi = 3.14;`
|
66 |
| - - 变量只能被定义一次,但是可以多次声明。 |
67 |
| -- 名字的**作用域**(namescope) |
| 73 | + - 变量只能被定义一次,但是可以多次声明。定义只出现在一个文件中,其他文件使用该变量时需要对其声明。 |
| 74 | +- 名字的**作用域**(namescope)`{}` |
| 75 | + - **第一次使用变量时再定义它**。 |
| 76 | + - 嵌套的作用域 |
| 77 | + - 同时存在全局和局部变量时,已定义局部变量的作用域中可用`::reused`显式访问全局变量reused。 |
| 78 | + - **但是用到全局变量时,尽量不适用重名的局部变量。** |
| 79 | +
|
| 80 | +#### 变量命名规范 |
| 81 | +1. 需体现实际意义 |
| 82 | +2. 变量名用小写字母 |
| 83 | +3. 自定义类名用大写字母开头:Sales_item |
| 84 | +4. 标识符由多个单词组成,中间须有明确区分:student_loan或studentLoan,不要用studentloan。 |
68 | 85 |
|
69 | 86 | ## 左值和右值
|
70 | 87 |
|
|
76 | 93 |
|
77 | 94 | ### 引用
|
78 | 95 |
|
| 96 | +> 一般说的引用是指的左值引用 |
79 | 97 | - **引用**:引用是一个对象的别名,引用类型引用(refer to)另外一种类型。如`int &refVal = val;`。
|
80 | 98 | - 引用必须初始化。
|
81 |
| -- 引用和它的初始值是**绑定bind**在一起的,而**不是拷贝**。 |
| 99 | +- 引用和它的初始值是**绑定bind**在一起的,而**不是拷贝**。一旦定义就不能更改绑定为其他的对象 |
82 | 100 |
|
83 | 101 | ### 指针
|
84 | 102 |
|
| 103 | +> int *p; //**指向int型对象**的指针 |
| 104 | +
|
85 | 105 | - 是一种 `"指向(point to)"`另外一种类型的复合类型。
|
86 |
| -- **定义**指针类型: `int *ip1;`,**从右向左读**,`ip1`是指向`int`类型的指针。 |
| 106 | +
|
| 107 | +- **定义**指针类型: `int *ip1;`,**从右向左读有助于阅读**,`ip1`是指向`int`类型的指针。 |
| 108 | +
|
87 | 109 | - 指针存放某个对象的**地址**。
|
| 110 | +
|
88 | 111 | - 获取对象的地址: `int i=42; int *p = &i;`。 `&`是**取地址符**。
|
| 112 | +
|
| 113 | +- 指针的类型与所指向的对象类型必须一致(均为同一类型int、double等) |
| 114 | +
|
89 | 115 | - 指针的值的四种状态:
|
90 | 116 | - 1.指向一个对象;
|
91 | 117 | - 2.指向紧邻对象的下一个位置;
|
92 | 118 | - 3.空指针;
|
93 | 119 | - 4.无效指针。
|
94 |
| -- 指针访问对象: `cout << *p;`, `*`是**解引用符**。 |
95 |
| -- 空指针不指向任何对象。 |
96 |
| -- `void*`指针可以存放**任意**对象的地址。 |
| 120 | + - >**对无效指针的操作均会引发错误,第二种和第三种虽为有效的,但理论上是不被允许的** |
| 121 | + |
| 122 | +- 指针访问对象: `cout << *p;`输出p指针所指对象的数据, `*`是**解引用符**。 |
| 123 | +
|
| 124 | +- 空指针不指向任何对象。使用`int *p=nullptr;`来使用空指针。 |
| 125 | +
|
| 126 | +- > 指针和引用的区别:引用本身并非一个对象,引用定义后就不能绑定到其他的对象了;指针并没有此限制,相当于变量一样使用。 |
| 127 | +
|
| 128 | +- > 赋值语句永远改变的是**左侧**的对象。 |
| 129 | +
|
| 130 | +- `void*`指针可以存放**任意**对象的地址。因无类型,仅操作内存空间,对所存对象无法访问。 |
| 131 | +
|
97 | 132 | - 其他指针类型必须要与所指对象**严格匹配**。
|
| 133 | +
|
98 | 134 | - 两个指针相减的类型是`ptrdiff_t`。
|
| 135 | +
|
99 | 136 | - 建议:初始化所有指针。
|
100 | 137 |
|
| 138 | +- `int* p1, p2;//*是对p1的修饰,所以p2还是int型` |
| 139 | +
|
101 | 140 | ## const限定符
|
102 | 141 |
|
103 | 142 | - 动机:希望定义一些不能被改变值的变量。
|
104 | 143 |
|
105 | 144 | ### 初始化和const
|
106 | 145 | - const对象**必须初始化**,且**不能被改变**。
|
107 |
| -- const变量默认不能被其他文件访问,非要访问,必须在指定const前加extern。 |
| 146 | +- const变量默认不能被其他文件访问,非要访问,必须在指定const定义之前加extern。要想在多个文件中使用const变量共享,定义和声明都加const关键字即可。 |
108 | 147 |
|
109 | 148 | ### const的引用
|
110 | 149 |
|
|
115 | 154 | ### 指针和const
|
116 | 155 |
|
117 | 156 | - **pointer to const**(指向常量的指针):不能用于改变其所指对象的值, 如 `const double pi = 3.14; const double *cptr = π`。
|
118 |
| -- **const pointer**:指针本身是常量,如 `int i = 0; int *const ptr = &i;` |
| 157 | +- **const pointer**:指针本身是常量,也就是说指针固定指向该对象,(存放在指针中的地址不变,地址所对应的那个对象值可以修改)如 `int i = 0; int *const ptr = &i;` |
119 | 158 |
|
120 | 159 | ### 顶层const
|
121 | 160 |
|
122 | 161 | - `顶层const`:指针本身是个常量。
|
123 | 162 | - `底层const`:指针指向的对象是个常量。拷贝时严格要求相同的底层const资格。
|
124 | 163 |
|
125 |
| -### `constexpr`和常量表达式 |
| 164 | +### `constexpr`和常量表达式(▲可选) |
126 | 165 |
|
127 | 166 | - 常量表达式:指值不会改变,且在编译过程中就能得到计算结果的表达式。
|
128 | 167 | - `C++11`新标准规定,允许将变量声明为`constexpr`类型以便由编译器来验证变量的值是否是一个常量的表达式。
|
|
134 | 173 | - 传统别名:使用**typedef**来定义类型的同义词。 `typedef double wages;`
|
135 | 174 | - 新标准别名:别名声明(alias declaration): `using SI = Sales_item;`(C++11)
|
136 | 175 |
|
137 |
| -### auto类型说明符 |
| 176 | +```cpp |
| 177 | +// 对于复合类型(指针等)不能代回原式来进行理解 |
| 178 | +typedef char *pstring; // pstring是char*的别名 |
| 179 | +const pstring cstr = 0; // 指向char的常量指针 |
| 180 | +// 如改写为const char *cstr = 0;不正确,为指向const char的指针 |
| 181 | +
|
| 182 | +// 辅助理解(可代回后加括号) |
| 183 | +// const pstring cstr = 0;代回后const (char *) cstr = 0; |
| 184 | +// const char *cstr = 0;即为(const char *) cstr = 0; |
| 185 | +``` |
| 186 | + |
| 187 | +### auto类型说明符 c++11 |
138 | 188 |
|
139 | 189 | - **auto**类型说明符:让编译器**自动推断类型**。
|
| 190 | +- 一条声明语句只能有一个数据类型,所以一个auto声明多个变量时只能相同的变量类型(包括复杂类型&和*)。`auto sz = 0, pi =3.14//错误` |
140 | 191 | - `int i = 0, &r = i; auto a = r;` 推断`a`的类型是`int`。
|
141 | 192 | - 会忽略`顶层const`。
|
142 |
| -- `const int ci = 1; const auto f = ci;`推断类型是`int`,需要自己加`const` |
143 |
| -- `C++11` |
| 193 | +- `const int ci = 1; const auto f = ci;`推断类型是`int`,如果希望是顶层const需要自己加`const` |
144 | 194 |
|
145 | 195 | ### decltype类型指示符
|
146 | 196 |
|
147 | 197 | - 从表达式的类型推断出要定义的变量的类型。
|
148 | 198 | - **decltype**:选择并返回操作数的**数据类型**。
|
149 | 199 | - `decltype(f()) sum = x;` 推断`sum`的类型是函数`f`的返回类型。
|
150 | 200 | - 不会忽略`顶层const`。
|
| 201 | +- 如果对变量加括号,编译器会将其认为是一个表达式,如int i-->(i),则decltype((i))得到结果为int&引用。 |
| 202 | +- 赋值是会产生引用的一类典型表达式,引用的类型就是左值的类型。也就是说,如果 i 是 int,则表达式 i=x 的类型是 int&。 |
151 | 203 | - `C++11`
|
152 | 204 |
|
153 | 205 | ## 自定义数据结构
|
154 | 206 |
|
155 | 207 | ### struct
|
156 | 208 |
|
| 209 | +> 尽量不要吧类定义和对象定义放在一起。如`struct Student{} xiaoming,xiaofang;` |
157 | 210 | - 类可以以关键字`struct`开始,紧跟类名和类体。
|
158 | 211 | - 类数据成员:类体定义类的成员。
|
159 | 212 | - `C++11`:可以为类数据成员提供一个**类内初始值**(in-class initializer)。
|
|
167 | 220 | - **预处理器**(preprocessor):确保头文件多次包含仍能安全工作。
|
168 | 221 | - 当预处理器看到`#include`标记时,会用指定的头文件内容代替`#include`
|
169 | 222 | - **头文件保护符**(header guard):头文件保护符依赖于预处理变量的状态:已定义和未定义。
|
| 223 | + - `#indef`已定义时为真 |
| 224 | + - `#inndef`未定义时为真 |
| 225 | + - 头文件保护符的名称需要唯一,且保持全部大写。养成良好习惯,不论是否该头文件被包含,要加保护符。 |
170 | 226 |
|
171 | 227 | ```cpp
|
172 |
| -#ifndef SALES_DATA_H |
| 228 | +#ifndef SALES_DATA_H //SALES_DATA_H未定义时为真 |
173 | 229 | #define SALES_DATA_H
|
174 | 230 | strct Sale_data{
|
175 | 231 | ...
|
176 | 232 | }
|
177 | 233 | #endif
|
178 |
| -``` |
| 234 | +``` |
0 commit comments