ShuangChenYue ShuangChenYue
首页
  • Cpp之旅
  • Cpp专栏
  • Effective_CPP
  • muduo网络库
  • Unix环境高级编程
  • Cpp提高编程
  • 计算机网络
  • 操作系统
  • 数据结构
  • Linux
  • 算法
  • 基础篇
  • MySql
  • Redis
  • 电子嵌入式通信协议
  • 深入浅出SSD
  • 文件系统
  • 汇编语言
  • STM32
  • 随笔(持续更新)
  • Git知识总结
  • Git 创建删除远程分支
  • nvm使用小结
  • 虚拟机固定 IP 地址
  • Shell 脚本学习笔记
  • VScode 插件 CodeGeeX 使用教程
  • KylinV10 将项目上传至 Github教程
  • KylinV10 安装 MySQL 教程(可防踩雷)
  • kylinV10-SP1 安装 QT
  • 高并发内存池
  • USBGUARD 项目编译环境配置
  • Power_Destory 项目
  • U 盘清除工具编译教程
  • 个人博客代码推送教程
  • HTML与CSS
  • JS学习
  • Vue3入门
  • Vue3进阶
  • 黑马Vue3
  • MFC编程随记
  • MFC实现ini配置文件的读取
  • MFC实现点击列表头排序
  • 贴图法美化Button按钮
  • 如何高效阅读嵌入式项目代码
  • NAND Flash
  • ARM 处理器
  • 嵌入式基础知识-存储器
  • 闪存存储和制造技术概述
  • 芯片IO驱动力
  • 主流先进封装技术介绍
  • 虎牙C++技术面经
  • 金山一面复习
  • 完美世界秋招 C++ 游戏开发面经(Cpp部分)
  • 博客搭建
  • 网站收藏箱
首页
  • Cpp之旅
  • Cpp专栏
  • Effective_CPP
  • muduo网络库
  • Unix环境高级编程
  • Cpp提高编程
  • 计算机网络
  • 操作系统
  • 数据结构
  • Linux
  • 算法
  • 基础篇
  • MySql
  • Redis
  • 电子嵌入式通信协议
  • 深入浅出SSD
  • 文件系统
  • 汇编语言
  • STM32
  • 随笔(持续更新)
  • Git知识总结
  • Git 创建删除远程分支
  • nvm使用小结
  • 虚拟机固定 IP 地址
  • Shell 脚本学习笔记
  • VScode 插件 CodeGeeX 使用教程
  • KylinV10 将项目上传至 Github教程
  • KylinV10 安装 MySQL 教程(可防踩雷)
  • kylinV10-SP1 安装 QT
  • 高并发内存池
  • USBGUARD 项目编译环境配置
  • Power_Destory 项目
  • U 盘清除工具编译教程
  • 个人博客代码推送教程
  • HTML与CSS
  • JS学习
  • Vue3入门
  • Vue3进阶
  • 黑马Vue3
  • MFC编程随记
  • MFC实现ini配置文件的读取
  • MFC实现点击列表头排序
  • 贴图法美化Button按钮
  • 如何高效阅读嵌入式项目代码
  • NAND Flash
  • ARM 处理器
  • 嵌入式基础知识-存储器
  • 闪存存储和制造技术概述
  • 芯片IO驱动力
  • 主流先进封装技术介绍
  • 虎牙C++技术面经
  • 金山一面复习
  • 完美世界秋招 C++ 游戏开发面经(Cpp部分)
  • 博客搭建
  • 网站收藏箱
  • Cpp之旅

  • Cpp专栏

    • 第2章 变量和基本类型
    • Cpp11新标准
    • 探索C++14新特性:更强大、更高效的编程
    • C++17 新特性
    • 协程
    • C++ 备忘清单
      • 1. C++ 数组
        • 1.1 定义
        • 1.2 操控
        • 1.3 展示
        • 1.4 多维
      • 2. C++ 条件
        • 2.1 if Clause
        • 2.2 Else if 语句
        • 2.3 三元运算符
        • 2.4 switch 语句
      • 3. C++ 循环
        • 3.1 While
        • 3.2 Do-while
        • 3.3 Continue 语句
        • 3.4 无限循环
        • 3.5 for_each(C++11起)
        • 3.6 基于范围(C++11起)
        • 3.7 中断语句
        • 3.8 Several variations
      • 4. C++ 函数
        • 4.1 参数和返回
        • 4.2 重载
        • 4.3 内置函数
        • 4.4 Lambda 表达式
      • 5. C++ 多线程
        • 5.1 多线程介绍
        • 5.2 线程的创建
        • 5.3 线程的销毁
        • 5.4 this_thread
        • 5.5 锁
        • 5.5.1 头文件
        • 5.5.2 锁的基本操作
        • 5.5.3 更简单的锁 std::lock_guard<Mutex>
        • 5.5.4 unique_lock<Mutex>
        • 5.5.5 std::adopt_lock
        • 5.5.6 std::try_to_lock
        • 5.5.7 std::defer_lock
        • 5.5.8 std::unique_lock::release
        • 5.5.9 std::call_once
        • 5.6 std::condition_variable
        • 5.6.1 创建条件变量
        • 5.6.2 等待条件变量被通知
        • 5.6.3 std::condition_variable::notify_one
        • 5.6.4 std::condition_variable::notify_all
        • 5.7 获取线程的运行结果
        • 5.7.1 创建异步任务
        • 5.7.2 获取异步任务的返回值
        • 5.7.3 std::async 的额外参数
        • 5.7.4 返回值的状态
        • 5.7.5 多个返回值
      • 6. C++ 预处理器
        • 6.1 预处理器
        • 6.2 includes
        • 6.3 Defines
        • 6.4 if
        • 6.5 Error
        • 6.6 宏
        • 6.7 令牌连接
        • 6.8 字符串话
        • 6.9 文件和行
  • Effetcive_CPP

  • muduo网络库

  • Unix环境高级编程

  • Cpp提高编程

  • CPP语言
  • Cpp专栏
霜晨月
2024-02-19
目录

C++ 备忘清单

# C++ 备忘清单

# 1. C++ 数组

# 1.1 定义

std::array<int,3> marks;	// 定义
marks[0] = 92;
marks[1] = 97;
marks[2] = 98;
// 定义和初始化
std::array<int,3> = {92,97,98};
// 有空成员
std::cout << marks[2];	// 输出:0
1
2
3
4
5
6
7
8

# 1.2 操控

┌─────┬─────┬─────┬─────┬─────┬─────┐
| 92  | 97  | 98  | 99  | 98  | 94  |
└─────┴─────┴─────┴─────┴─────┴─────┘
   0     1     2     3     4     5
--------------------------------------------------------
std::array<int, 6> = marks = {
    92, 97, 98, 99, 98, 94
};
// 打印第一个元素
std::cout << marks[0];
// 将第2个元素更改为99
marks[1] = 99;
// 从用户那里获取输入
std::cin >> marks[2];
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 1.3 展示

char ref[5] = {'R', 'e', 'f'};
// j基于范围的 for 循环
for (const int &n : ref) {
    std::cout << std::string(1,n);
}
// 传统的 for 循环
for(int i = 0; i < sizeof(ref); ++i) {
    std::cout << ref[i];
}
1
2
3
4
5
6
7
8
9

# 1.4 多维

     j0   j1   j2   j3   j4   j5
   ┌────┬────┬────┬────┬────┬────┐
i0 | 1  | 2  | 3  | 4  | 5  | 6  |
   ├────┼────┼────┼────┼────┼────┤
i1 | 6  | 5  | 4  | 3  | 2  | 1  |
   └────┴────┴────┴────┴────┴────┘
------------------------------------------------------------
int x[2][6] = {
	{1, 2, 3, 4, 5, 6}, {6, 5, 4, 3, 2, 1}
};
for(int i = 0; i < 2; ++i) {
    for(int j = 0; j < 6; ++j) {
        std::cout << x[i][j] << " ";
    }
}
// 输出:1 2 3 4 5 6 6 5 4 3 2 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 2. C++ 条件

# 2.1 if Clause

if (a == 10) {
    // do something
}
int number = 16;
if (number % 2 == 0)
{
    std::cout << "even";
}
else
{
    std::cout << "odd";
}
// 输出: even
1
2
3
4
5
6
7
8
9
10
11
12
13

# 2.2 Else if 语句

int score = 99;
if (score == 100) {
    std::cout << "Superb";
}
else if (score >= 90) {
    std::cout << "Excellent";
}
else if (score >= 80) {
    std::cout << "Very Good";
}
else if (score >= 70) {
    std::cout << "Good";
}
else if (score >= 60)
    std::cout << "OK";
else
    std::cout << "What?";
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 2.3 三元运算符

           ┌── True ──┐
Result = Condition ? Exp1 : Exp2;
           └───── False ─────┘
-----------------------------------------------------------
int x = 3, y = 5, max;
max = (x > y) ? x : y;
// 输出: 5
std::cout << max << std::endl;
int x = 3, y = 5, max;
if (x > y) {
    max = x;
} else {
    max = y;
}
// 输出: 5
std::cout << max << std::endl;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 2.4 switch 语句

int num = 2;
switch (num) {
    case 0:
        std::cout << "Zero";
        break;
    case 1:
        std::cout << "One";
        break;
    case 2:
        std::cout << "Two";
        break;
    case 3:
        std::cout << "Three";
        break;
    default:
        std::cout << "What?";
        break;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 3. C++ 循环

# 3.1 While

int i = 0;
while(i < 6) {
    std::cout << ++i;
}
// 输出: 012345
1
2
3
4
5

# 3.2 Do-while

int i = 1;
do {
    std::cout << i++;
} while (i <= 5);
// 输出: 12345
1
2
3
4
5

# 3.3 Continue 语句

for (int i = 0; i < 10; i++) {
    if (i % 2 == 0) {
        continue;
    }
    std::cout << i;
} // 输出: 13579
1
2
3
4
5
6

# 3.4 无限循环

while (true) { // true or 1
    std::cout << "无限循环";
}
for (;;) {
    std::cout << "无限循环";
}
for(int i = 1; i > 0; i++) {
    std::cout << "infinite loop";
}
1
2
3
4
5
6
7
8
9

# 3.5 for_each(C++11起)

#include <iostream>
int main()
{
    auto print = [](int num) {
      std::cout << num << std::endl;
    };
    std::array<int, 4> arr = {1, 2, 3, 4};
    std::for_each(arr.begin(), arr.end(), print);
    return 0;
}
1
2
3
4
5
6
7
8
9
10

# 3.6 基于范围(C++11起)

for (int n : {1, 2, 3, 4, 5}) {
    std::cout << n << " ";
}
// 输出: 1 2 3 4 5
std::string hello = "Quick Reference.ME";
for (char c: hello)
{
    std::cout << c << " ";
}
// 输出: Q u i c k R e f . M E 
1
2
3
4
5
6
7
8
9
10

# 3.7 中断语句

int password, times = 0;
while (password != 1234) {
    if (times++ >= 3) {
        std::cout << "Locked!\n";
        break;
    }
    std::cout << "Password: ";
    std::cin >> password; // input
}
1
2
3
4
5
6
7
8
9

# 3.8 Several variations

for (int i = 0, j = 2; i < 3; i++, j--){
    std::cout << "i=" << i << ",";
    std::cout << "j=" << j << ";";
}
// 输出: i=0,j=2;i=1,j=1;i=2,j=0;
1
2
3
4
5

# 4. C++ 函数

# 4.1 参数和返回

// add 是一个接受 2 个整数并返回整数的函数
#include <iostream>
int add(int a, int b) {
    return a + b;  
}
int main() {
    std::cout << add(10, 20); 
}
1
2
3
4
5
6
7
8

# 4.2 重载

void fun(string a, string b) {
    std::cout << a + " " + b;
}
void fun(string a) {
    std::cout << a;
}
void fun(int a) {
    std::cout << a;
}
1
2
3
4
5
6
7
8
9

# 4.3 内置函数

#include <iostream>
#include <cmath> // 导入库
 
int main() {
    // sqrt() 来自 cmath
    std::cout << sqrt(9);
}
1
2
3
4
5
6
7

# 4.4 Lambda 表达式

Lambda 表达式可以在函数内定义,可以理解为在函数内定义的临时函数。格式:

auto func = []() -> return_type { };
1

[] 为捕获列表,能够捕获其所在函数的局部变量

  • 一个空的捕获列表代表Lambda表达式不捕获任何的变量

  • 对于值捕获,直接在中括号中填写要捕获的变量即可:

    int val = 5;
    auto func = [val]() -> return_type { };
    
    1
    2

对于引用捕获,需要在捕获的变量前添加 &:

string str("hello world!");
auto func = [&str]() -> return_type { };
1
2

如果变量太多,需要编译器根据我们编写的代码自动捕获,可以采用隐式捕获的方式。

  • 全部值捕获:

    int val1, val2;
    auto func = [=]() -> int
    {
    	return val1 + val2;
    };
    
    1
    2
    3
    4
    5
  • 全部引用捕获:

    string str1("hello"), str2("word!");
    auto func = [&]() -> string
    {
        return str1 + str2;
    }
    
    1
    2
    3
    4
    5
  • 混合隐式捕获:

    如果希望对一部分变量采用值捕获,对其他变量采用引用捕获,可以混合使用:

    int val1 = 123, vla2 = 456;
    string str1("123"), str2(456);
    auto func1 = [=, &str1]() -> int
    {
        return val1 == std::stoi(str1) ? val1 : val2;
    };
    auto func2 = [&, val1]() -> int
    {
      	return str1 == std::to_string(val1) ? str1 : str2;  
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
  • () 是参数列表,我们只需要按照普通函数的使用方法来使用即可

  • return_type 是函数的返回类型,-> return_type 可以不写,编译器会自动推导

  • {} 中的内容就是函数体,依照普通函数的使用方法使用即可

此处给出一个 Lambda 表达式的实际使用例子(当然可以使用 str::copy):

// vec中包含1, 2, 3, 4, 5
std::vector<int> vec({1,2,3,4,5});
std::for_each(vec.begin(), vec.end(),[](int& ele) -> void
{
	std::cout << ele << " ";
});
1
2
3
4
5
6

# 5. C++ 多线程

# 5.1 多线程介绍

g++编译选项:-std=c++11。包含头文件:

  • #include <thread>:C++多线程库
  • #include <mutex>:C++互斥量库
  • #include <future>:C++异步库

# 5.2 线程的创建

以普通函数作为线程入口函数:

void entry_1() { }
void entry_2(int val) { }

std::thread my_thread_1(entry_1);
std::thread my_thread_2(entry_2, 5);
1
2
3
4
5

以类对象作为线程入口函数:

class Entry {
  	void operator()() { }
    void entry_function() { }
};
Entry entry;
// 调用 operator()()
std::thread my_thread_1(entry);
// 调用 Entry::entry_function
std::thread my_thread_2(&Entry::entry_function, &entry);
1
2
3
4
5
6
7
8
9

以 lambda 表达式作为线程入口函数:

std::thread my_thread([]() -> void
{
	// ...
});
1
2
3
4

# 5.3 线程的销毁

thread my_thread;
// 阻塞
my_thread.join();
// 非阻塞
my_thread.detach();
1
2
3
4
5

# 5.4 this_thread

// 获取当前线程 ID
std::this_thread::get_id();
// 是当前线程休眠一段指定时间
std::this_thread::sleep_for();
// 使当前线程休眠到指定时间
std::this_thread::sleep_until();
// 暂停当前线程的执行,让别的线程执行
std::this_thread::yield();
1
2
3
4
5
6
7
8

# 5.5 锁

# 5.5.1 头文件

#include <mutex>
1

# 5.5.2 锁的基本操作

创建锁

std::mutex m;
1

上锁

m.lock();
1

解锁

m.unlock();
1

尝试上锁:成功返回 true,失败返回 false

m.try_lock();
1

解锁

m.unlock();
1

# 5.5.3 更简单的锁 std::lock_guard<Mutex>

构造时上锁,析构时解锁

std::mutex m;
std::lock_guard<std::mutex> lock(m);
1
2

额外参数:std::adopt_lock:只需解锁,无需上锁

// 手动上锁
m.lock();
std::lock_guard<mutex> lock(m, std::adopt_lock);
1
2
3

# 5.5.4 unique_lock<Mutex>

构造上锁,析构解锁

std::mutex m;
std::unique_lock<mutex> lock(m);
1
2

# 5.5.5 std::adopt_lock

只需解锁,无需上锁

// 手动上锁
m.lock();
std::unique_lock<mutex> lock(m, std::adopt_lock);
1
2
3

# 5.5.6 std::try_to_lock

尝试上锁,可以通过 std::unique_lock<Mutex>::owns_lock() 查看状态

std::unique_lock<mutex> lock(m, std::try_to_lock);
if(lock.owns_lock()){
    // 拿到了锁
} else {
    // 没有
}
1
2
3
4
5
6

# 5.5.7 std::defer_lock

绑定锁,但不上锁

std::unique_lock<mutex> lock(m, std::defer_lock);
lock.lock();
lock.unlock();
1
2
3

# 5.5.8 std::unique_lock<Mutex>::release

返回所管理的 mutex 对象指针, 释放所有权。 一旦释放了所有权,那么如果原来互斥量处于互斥状态,程序员有责任手动解锁。

# 5.5.9 std::call_once

当多个线程通过这个函数调用一个可调用对象时,只会有一个线程成功调用。

std::once_flag flag;
void foo() { }
std::call_once(flag, foo);
1
2
3

# 5.6 std::condition_variable

# 5.6.1 创建条件变量

std::condition_variable cond;
1

# 5.6.2 等待条件变量被通知

std::unique_lock<std::mutex> lock;
extern bool predicate();
// 调用方式1
cond wait(lock);
// 调用方式2
cond.wait(lock, predicate);
1
2
3
4
5
6
  • wait 不断地尝试重新获取并加锁该互斥量,如果获取不到,它就卡在这里并反复尝试重新获取,如果获取到了,执行流程就继续往下走
  • wait 在获取到互斥量并加锁了互斥量之后:
    • 如果 wait 被提供了可调用对象,那么就执行这个可调用对象:
      • 如果返回值为 false,那么 wait 继续加锁,直到再次被 notified
      • 如果返回值为 true,那么 wait 返回,继续执行流程
    • 如果 wait 没有第二个参数,那么直接返回,继续执行

# 5.6.3 std::condition_variable::notify_one

notify_one 唤醒一个调用 wait 的线程。注意在唤醒之前要解锁,否则调用 wait 的线程也会因为无法加锁而阻塞。

# 5.6.4 std::condition_variable::notify_all

唤醒所有调用 wait 的线程。

# 5.7 获取线程的运行结果

头文件

#include <future>
1

# 5.7.1 创建异步任务

double func(int val);
// 使用 std::async 创建异步任务
// 使用 std::future 获取结果
// future 模板中存放返回值类型
std::future<double> result = std::saync(func, 5);
1
2
3
4
5

# 5.7.2 获取异步任务的返回值

等待异步任务结束,但是不获取返回值:

result.wait();
1

获取异步任务的返回值:

int val = result.get();
1

注:

  • get()返回右值,因此只可调用一次
  • 只要调用上述任意函数,线程就会一直阻塞到返回值可用(入口函数运行结束)

# 5.7.3 std::async 的额外参数

额外参数可以被放在 std::async 的第一个参数位置,用于设定 std::async 的行为

  • std::launch::deferred :入口函数的运行会被推迟到 std::future<T>::get() 或者 std::future<T>::wait() 被调用时。此时调用线程会直接运行线程入口函数,换言之,不会创建子线程
  • std::launch::async :立即创建子线程,并运行线程入口函数
  • std::launch::deferred | std::launch::async :默认值,由系统自行决定

# 5.7.4 返回值的状态

让当前线程等待一段时间(等待到指定时间点),以期待返回值准备好:

extern double foo(int val) { }
std::future<double> result = async(foo, 5);
// 返回值类型
std::future_status status;
// 等待一段时间
status = result.wait_for(std::chrono::seconds(1));
// 等待到某一时间点
status = result.wait_for(std::chrono::now() + std::chrono::seconds(1));
1
2
3
4
5
6
7
8

在指定的时间过去后,可以获取等待的结果:

// 返回值已经准备好
if(status == std::future_status::ready)
{
    
} else if(status == std::future_status::timeout) {
    // 超时:尚未准备好
} else if(status == std::future_status::deferred) {
    // 尚未启动: std::launch::deferred
}
1
2
3
4
5
6
7
8
9

# 5.7.5 多个返回值

std::shared_future<T> result;
1

如果要多次获取结果,可以使用 std::shared_future,其会返回结果的一个拷贝。

对于不可拷贝对象,可以在 std::shared_future 中存储对象的指针,而非指针本身。

# 6. C++ 预处理器

# 6.1 预处理器

if (opens new window) elif (opens new window)
else (opens new window) endif (opens new window)
ifdef (opens new window) ifndef (opens new window)
define (opens new window) undef (opens new window)
include (opens new window) line (opens new window)
error (opens new window) pragma (opens new window)
defined (opens new window) __has_include (opens new window)
__has_cpp_attribute (opens new window) export (opens new window)
import (opens new window) module (opens new window)

# 6.2 includes

#include "iostream"
#include <iostream>
1
2

# 6.3 Defines

#define FOO
#define FOO "hello"
#undef FOO
1
2
3

# 6.4 if

#ifdef DEBUG
	console.log('hi');
#elif defined VERBOSE
...
#else
...
#endif
1
2
3
4
5
6
7

# 6.5 Error

#if VERSION === 2.0
	#error Unsupported
	#warning Not really supported
#endif
1
2
3
4

# 6.6 宏

#define DEG(x)((x)*57.29)
1

# 6.7 令牌连接

#define DST(name) name##_s name##_t
DST(object); #=> object_s object_t;
1
2

# 6.8 字符串话

#define STR(name) #name
char *a = STR(object); #=> char *a = "object";
1
2

# 6.9 文件和行

#define LOG(msg) console.log(__FILE__,__LINE__,msg)
#=> console.log("file.txt", 3, "hey")
1
2
上次更新: 2024/6/3 14:54:44
协程
条款1-4 让自己习惯Cpp

← 协程 条款1-4 让自己习惯Cpp→

Theme by Vdoing | Copyright © 2023-2024 霜晨月
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式