Skip to content

Commit 47db5af

Browse files
committed
1. 修改第二章使用线程中传递参数的措辞以及代码格式和测试链接
2. 修改第三章Markdown格式问题 3. 修改第五章的前言总结措辞
1 parent e944457 commit 47db5af

File tree

3 files changed

+10
-10
lines changed

3 files changed

+10
-10
lines changed

md/02使用线程.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -395,16 +395,16 @@ void f(){
395395
396396
### 传递参数
397397
398-
向可调用对象或函数传递参数很简单,我们前面也都写了,只需要将这些参数作为 `std::thread` 的构造参数即可。需要注意的是,这些参数会复制到新线程的内存空间中,即使函数中的参数是引用,依然**实际是复制**
398+
向可调用对象传递参数很简单,我们前面也都写了,只需要将这些参数作为 `std::thread` 的构造参数即可。需要注意的是,这些参数会复制到新线程的内存空间中,即使函数中的参数是引用,依然**实际是复制**
399399
400400
```cpp
401401
void f(int, const int& a);
402402
403403
int n = 1;
404-
std::thread t(f, 3, n);
404+
std::thread t{ f, 3, n };
405405
```
406406
407-
线程对象 t 的构造没有问题,可以通过编译,但是这个 n 实际上并没有按引用传递,而按值复制的。我们可以打印地址来验证我们的猜想。
407+
线程对象 t 的构造没有问题,可以通过编译,但是这个 n 实际上并没有按引用传递,而是按值复制的。我们可以打印地址来验证我们的猜想。
408408
409409
```cpp
410410
void f(int, const int& a) { // a 并非引用了局部对象 n
@@ -414,12 +414,12 @@ void f(int, const int& a) { // a 并非引用了局部对象 n
414414
int main() {
415415
int n = 1;
416416
std::cout << &n << '\n';
417-
std::thread t(f, 3, n);
417+
std::thread t{ f, 3, n };
418418
t.join();
419419
}
420420
```
421421
422-
[运行代码](https://godbolt.org/z/TzWeW5rxh),打印的地址截然不同。
422+
[运行代码](https://godbolt.org/z/YPhbWbxYn),打印的地址截然不同。
423423
424424
可以通过编译,但通常这不符合我们的需求,因为我们的函数中的参数是引用,我们自然希望能引用调用方传递的参数,而不是复制。如果我们的 f 的形参类型不是 **const 的引用**,则会产生一个[编译错误](https://godbolt.org/z/3nMb4asnG)
425425
@@ -433,12 +433,12 @@ void f(int, int& a) {
433433
int main() {
434434
int n = 1;
435435
std::cout << &n << '\n';
436-
std::thread t(f, 3, std::ref(n));
436+
std::thread t { f, 3, std::ref(n) };
437437
t.join();
438438
}
439439
```
440440
441-
> [运行代码](https://godbolt.org/z/hTP3ex4W7),打印地址完全相同。
441+
> [运行代码](https://godbolt.org/z/zW6h1EK59),打印地址完全相同。
442442
443443
我们来解释一下,“**ref**” 其实就是 “**reference**”(引用)的缩写,意思也很简单,返回“引用”,当然了,不是真的返回引用,它们返回一个包装类 [`std::reference_wrapper`](https://zh.cppreference.com/w/cpp/utility/functional/reference_wrapper),顾名思义,这个类就是包装引用对象类模板,将对象包装,可以隐式转换为被包装对象的引用。
444444

md/03共享数据.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,11 +1015,11 @@ CPU 变量的概念很好理解。就像线程变量为每个线程提供独立
10151015
10161016
> ### 全局变量
10171017
1018-
- 拥有***静态(static)***[存储期](https://zh.cppreference.com/w/cpp/language/storage_duration#.E5.AD.98.E5.82.A8.E6.9C.9F),它的存储在**程序**开始时分配,并在程序结束时解分配;且它在主函数执行之前进行[初始化](https://zh.cppreference.com/w/cpp/language/initialization#.E9.9D.9E.E5.B1.80.E9.83.A8.E5.8F.98.E9.87.8F)。
1018+
- 拥有 ***静态(static)*** [存储期](https://zh.cppreference.com/w/cpp/language/storage_duration#.E5.AD.98.E5.82.A8.E6.9C.9F),它的存储在**程序**开始时分配,并在程序结束时解分配;且它在主函数执行之前进行[初始化](https://zh.cppreference.com/w/cpp/language/initialization#.E9.9D.9E.E5.B1.80.E9.83.A8.E5.8F.98.E9.87.8F)。
10191019
10201020
> ### 线程变量
10211021
1022-
- 拥有***线程(thread)***存储期。它的存储在**线程**开始时分配,并在线程结束时解分配。每个线程拥有它自身的对象实例。只有声明为 thread_local 的对象拥有此存储期(不考虑非标准用法)。它的初始化需要考虑局部与非局部两种情况:
1022+
- 拥有 ***线程(thread)*** 存储期。它的存储在**线程**开始时分配,并在线程结束时解分配。每个线程拥有它自身的对象实例。只有声明为 thread_local 的对象拥有此存储期(不考虑非标准用法)。它的初始化需要考虑局部与非局部两种情况:
10231023
- 非局部变量:所有具有线程局部存储期的非局部变量的初始化,会**作为线程启动的一部分进行**,并按顺序早于线程函数的执行开始。
10241024
- 静态局部变量[^4]:控制流首次**经过它的声明**时才会被初始化(除非它被[零初始化](https://zh.cppreference.com/w/cpp/language/zero_initialization)或[常量初始化](https://zh.cppreference.com/w/cpp/language/constant_initialization))。在其后所有的调用中,声明都会被跳过。
10251025

md/05内存模型与原子操作.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,4 +681,4 @@ print("end"); // 2
681681

682682
不禁止就是有可能,但是我们无需在乎,**就算真的 CPU 将 end 重排到 start 前面了,也得在可观测行为发生前回溯了**。所以我一直在强调,这些东西,**我们无需在意**
683683

684-
好了,到此,基本认识也就足够了,以上的示例更多的是泛指,知到其表达的意思就好,这些还是简单直接且符合直觉的。
684+
好了,到此,基本认识也就足够了,以上的示例更多的是泛指,知道其表达的意思就好,这些还是简单直接且符合直觉的。

0 commit comments

Comments
 (0)