Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion excersize/ch04.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ int main()
{
vector<int> ivec{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };

for (auto i : ivec)
for (auto &i : ivec)
{
cout << ((i & 0x1) ? i * 2 : i) << " ";
}
Expand Down
7 changes: 7 additions & 0 deletions notes/ch01.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ UNIX和Mac下键盘输入文件结束符:`ctrl+d`,Windows下:`ctrl+z`

- 单行注释: `//`
- 多行注释: `/**/`。编译器将`/*`和`*/`之间的内容都作为注释内容忽略。注意不能嵌套。
```cpp
#define SALESITEM_H
/*
* 多行注释格式
* 每一行加一个*
*/
```

## while语句

Expand Down
88 changes: 72 additions & 16 deletions notes/ch02.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,17 @@
- 使用空格连接,继承自C。
- 字符字面值:单引号, `'a'`
- 字符串字面值:双引号, `"Hello World""`
- 分多行书写字符串。
```
std:cout<<"wow, a really, really long string"
"literal that spans two lines" <<std::endl;
```
- 转义序列。`\n`、`\t`等。
- 布尔字面值。`true`,`false`。
- 指针字面值。`nullptr`

> 字符串型实际上时常量字符构成的数组,结尾处以`'\0'`结束,所以字符串类型实际上长度比内容多1。

## 变量

**变量**提供一个**具名**的、可供程序操作的存储空间。 `C++`中**变量**和**对象**一般可以互换使用。
Expand All @@ -56,15 +63,25 @@
- 初始化 = 创建变量 + 赋予初始值
- 赋值 = 擦除对象的当前值 + 用新值代替
- **列表初始化**:使用花括号`{}`,如`int units_sold{0};`
- 默认初始化:定义时没有指定初始值会被默认初始化;在函数体内部的内置类型变量将不会被初始化。
- 默认初始化:定义时没有指定初始值会被默认初始化;**在函数体内部的内置类型变量将不会被初始化**
- 建议初始化每一个内置类型的变量。

### 变量的**声明**(declaration) vs **定义**(define)
- 为了支持分离式编译,`C++`将声明和定义区分开。**声明**使得名字为程序所知。**定义**负责创建与名字关联的实体。
- **extern**:只是说明变量定义在其他地方。
- 只声明而不定义: 在变量名前添加关键字 `extern`,如`extern int i;`。但如果包含了初始值,就变成了定义:`extern double pi = 3.14;`
- 变量只能被定义一次,但是可以多次声明。
- 名字的**作用域**(namescope)
- 变量只能被定义一次,但是可以多次声明。定义只出现在一个文件中,其他文件使用该变量时需要对其声明。
- 名字的**作用域**(namescope)`{}`
- **第一次使用变量时再定义它**。
- 嵌套的作用域
- 同时存在全局和局部变量时,已定义局部变量的作用域中可用`::reused`显式访问全局变量reused。
- **但是用到全局变量时,尽量不适用重名的局部变量。**

#### 变量命名规范
1. 需体现实际意义
2. 变量名用小写字母
3. 自定义类名用大写字母开头:Sales_item
4. 标识符由多个单词组成,中间须有明确区分:student_loan或studentLoan,不要用studentloan。

## 左值和右值

Expand All @@ -76,35 +93,57 @@

### 引用

> 一般说的引用是指的左值引用
- **引用**:引用是一个对象的别名,引用类型引用(refer to)另外一种类型。如`int &refVal = val;`。
- 引用必须初始化。
- 引用和它的初始值是**绑定bind**在一起的,而**不是拷贝**。
- 引用和它的初始值是**绑定bind**在一起的,而**不是拷贝**。一旦定义就不能更改绑定为其他的对象

### 指针

> int *p; //**指向int型对象**的指针

- 是一种 `"指向(point to)"`另外一种类型的复合类型。
- **定义**指针类型: `int *ip1;`,**从右向左读**,`ip1`是指向`int`类型的指针。

- **定义**指针类型: `int *ip1;`,**从右向左读有助于阅读**,`ip1`是指向`int`类型的指针。

- 指针存放某个对象的**地址**。

- 获取对象的地址: `int i=42; int *p = &i;`。 `&`是**取地址符**。

- 指针的类型与所指向的对象类型必须一致(均为同一类型int、double等)

- 指针的值的四种状态:
- 1.指向一个对象;
- 2.指向紧邻对象的下一个位置;
- 3.空指针;
- 4.无效指针。
- 指针访问对象: `cout << *p;`, `*`是**解引用符**。
- 空指针不指向任何对象。
- `void*`指针可以存放**任意**对象的地址。
- >**对无效指针的操作均会引发错误,第二种和第三种虽为有效的,但理论上是不被允许的**

- 指针访问对象: `cout << *p;`输出p指针所指对象的数据, `*`是**解引用符**。

- 空指针不指向任何对象。使用`int *p=nullptr;`来使用空指针。

- > 指针和引用的区别:引用本身并非一个对象,引用定义后就不能绑定到其他的对象了;指针并没有此限制,相当于变量一样使用。

- > 赋值语句永远改变的是**左侧**的对象。

- `void*`指针可以存放**任意**对象的地址。因无类型,仅操作内存空间,对所存对象无法访问。

- 其他指针类型必须要与所指对象**严格匹配**。

- 两个指针相减的类型是`ptrdiff_t`。

- 建议:初始化所有指针。

- `int* p1, p2;//*是对p1的修饰,所以p2还是int型`

## const限定符

- 动机:希望定义一些不能被改变值的变量。

### 初始化和const
- const对象**必须初始化**,且**不能被改变**。
- const变量默认不能被其他文件访问,非要访问,必须在指定const前加extern
- const变量默认不能被其他文件访问,非要访问,必须在指定const定义之前加extern。要想在多个文件中使用const变量共享,定义和声明都加const关键字即可

### const的引用

Expand All @@ -115,14 +154,14 @@
### 指针和const

- **pointer to const**(指向常量的指针):不能用于改变其所指对象的值, 如 `const double pi = 3.14; const double *cptr = &pi;`。
- **const pointer**:指针本身是常量,如 `int i = 0; int *const ptr = &i;`
- **const pointer**:指针本身是常量,也就是说指针固定指向该对象,(存放在指针中的地址不变,地址所对应的那个对象值可以修改)如 `int i = 0; int *const ptr = &i;`

### 顶层const

- `顶层const`:指针本身是个常量。
- `底层const`:指针指向的对象是个常量。拷贝时严格要求相同的底层const资格。

### `constexpr`和常量表达式
### `constexpr`和常量表达式(▲可选)

- 常量表达式:指值不会改变,且在编译过程中就能得到计算结果的表达式。
- `C++11`新标准规定,允许将变量声明为`constexpr`类型以便由编译器来验证变量的值是否是一个常量的表达式。
Expand All @@ -134,26 +173,40 @@
- 传统别名:使用**typedef**来定义类型的同义词。 `typedef double wages;`
- 新标准别名:别名声明(alias declaration): `using SI = Sales_item;`(C++11)

### auto类型说明符
```cpp
// 对于复合类型(指针等)不能代回原式来进行理解
typedef char *pstring; // pstring是char*的别名
const pstring cstr = 0; // 指向char的常量指针
// 如改写为const char *cstr = 0;不正确,为指向const char的指针

// 辅助理解(可代回后加括号)
// const pstring cstr = 0;代回后const (char *) cstr = 0;
// const char *cstr = 0;即为(const char *) cstr = 0;
```

### auto类型说明符 c++11

- **auto**类型说明符:让编译器**自动推断类型**。
- 一条声明语句只能有一个数据类型,所以一个auto声明多个变量时只能相同的变量类型(包括复杂类型&和*)。`auto sz = 0, pi =3.14//错误`
- `int i = 0, &r = i; auto a = r;` 推断`a`的类型是`int`。
- 会忽略`顶层const`。
- `const int ci = 1; const auto f = ci;`推断类型是`int`,需要自己加`const`
- `C++11`
- `const int ci = 1; const auto f = ci;`推断类型是`int`,如果希望是顶层const需要自己加`const`

### decltype类型指示符

- 从表达式的类型推断出要定义的变量的类型。
- **decltype**:选择并返回操作数的**数据类型**。
- `decltype(f()) sum = x;` 推断`sum`的类型是函数`f`的返回类型。
- 不会忽略`顶层const`。
- 如果对变量加括号,编译器会将其认为是一个表达式,如int i-->(i),则decltype((i))得到结果为int&引用。
- 赋值是会产生引用的一类典型表达式,引用的类型就是左值的类型。也就是说,如果 i 是 int,则表达式 i=x 的类型是 int&。
- `C++11`

## 自定义数据结构

### struct

> 尽量不要吧类定义和对象定义放在一起。如`struct Student{} xiaoming,xiaofang;`
- 类可以以关键字`struct`开始,紧跟类名和类体。
- 类数据成员:类体定义类的成员。
- `C++11`:可以为类数据成员提供一个**类内初始值**(in-class initializer)。
Expand All @@ -167,12 +220,15 @@
- **预处理器**(preprocessor):确保头文件多次包含仍能安全工作。
- 当预处理器看到`#include`标记时,会用指定的头文件内容代替`#include`
- **头文件保护符**(header guard):头文件保护符依赖于预处理变量的状态:已定义和未定义。
- `#indef`已定义时为真
- `#inndef`未定义时为真
- 头文件保护符的名称需要唯一,且保持全部大写。养成良好习惯,不论是否该头文件被包含,要加保护符。

```cpp
#ifndef SALES_DATA_H
#ifndef SALES_DATA_H //SALES_DATA_H未定义时为真
#define SALES_DATA_H
strct Sale_data{
...
}
#endif
```
```
14 changes: 10 additions & 4 deletions notes/ch03.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,20 @@
| `s1=s2` | 用`s2`的副本代替`s1`中原来的字符 |
| `s1==s2` | 如果`s1`和`s2`中所含的字符完全一样,则它们相等;`string`对象的相等性判断对字母的大小写敏感 |
| `s1!=s2` | 同上 |
| `<`, `<=`, `>`, `>=` | 利用字符在字典中的顺序进行比较,且对字母的大小写敏感 |
| `<`, `<=`, `>`, `>=` | 利用字符在字典中的顺序进行比较,且对字母的大小写敏感(对第一个不相同的位置进行比较) |

- string io:
- 执行读操作`>>`:忽略掉开头的空白(包括空格、换行符和制表符),直到遇到下一处空白为止。
- `getline`:读取一整行,**包括空白符**。
- 字符串字面值和string是不同的类型。
- `s.size()`返回的时`string::size_type`类型,记住是一个**无符号**类型的值,不要和`int`混用
- `s1+s2`使用时,保证至少一侧是string类型。`string s1 = "hello" + "world" // 错误,两侧均为字符串字面值`
- **字符串字面值和string是不同的类型。**

### 处理string对象中的字符

- **ctype.h vs. cctype**:C++修改了c的标准库,名称为去掉`.h`,前面加`c`。
> 如c++版本为`cctype`,c版本为`ctype.h`
- **尽量使用c++版本的头文件**,即`cctype`

`cctype`头文件中定义了一组标准函数:

Expand All @@ -71,6 +75,7 @@
| `toupper(c)` | 当`c`是小写字母,输出对应的大写字母;否则原样输出`c` |

- 遍历字符串:使用**范围for**(range for)语句: `for (auto c: str)`,或者 `for (auto &c: str)`使用引用直接改变字符串中的字符。 (C++11)
- `str[x]`,[]输入参数为`string::size_type`类型,给出`int`整型也会自动转化为该类型

## vector
- vector是一个**容器**,也是一个类模板;
Expand Down Expand Up @@ -135,7 +140,7 @@
- **迭代器(iterator)**:每种标准容器都有自己的迭代器。`C++`倾向于用迭代器而不是下标遍历元素。
- **const_iterator**:只能读取容器内元素不能改变。
- **箭头运算符**: 解引用 + 成员访问,`it->mem`等价于 `(*it).mem`
- **谨记**:但凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素
- **谨记**:但凡是使用了**迭代器**的循环体,都**不要**向迭代器所属的容器**添加元素**

标准容器迭代器的运算符:

Expand Down Expand Up @@ -199,10 +204,11 @@ C标准库String函数,定义在`<cstring>` 中:
| `strcat(p1, p2)` | 将`p2`附加到`p1`之后,返回`p1` |
| `strcpy(p1, p2)` | 将`p2`拷贝给`p1`,返回`p1` |

**尽量使用vector和迭代器,少用数组**
## 多维数组

- **多维数组的初始化**: `int ia[3][4] = {{0,1,2,3}, ...}`。
- 使用范围for语句时,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型
- 使用范围for语句时,除了最内层的循环外,其他所有循环的控制变量都应该是**引用**类型

## 指针vs引用

Expand Down
Loading