C++ 杂记
C++ 杂记
代码记录
随机 ID 生成函数
根据高分辨率的时钟为种子,生成指定长度的随机 ID 的函数
1 | // 生成指定长度的随机 ID |
1 | using std::chrono::high_resolution_clock; // 这行代码引入了 `std::chrono::high_resolution_clock`,这是一个用于测量时间的标准库类。 |
1 | static thread_local std::mt19937 rng( |
这行代码定义了一个静态局部变量 rng,它是一个 std::mt19937 类型的伪随机数生成器。通过使用当前时间的高分辨率时钟的计数作为种子,我们创建了一个每次函数调用时都会生成不同随机数序列的生成器。
1 | static const std::string characters( |
这行代码定义了一个静态常量字符串 characters,它包含了用于生成随机 ID 的字符集。它包括数字、大写字母和小写字母。
1 | std::string id(length, '0'); |
这行代码创建了一个名为 id 的 std::string 对象,长度为 length,并将其初始化为由字符 '0' 组成的字符串。
1 | std::uniform_int_distribution<int> uniform(0, int(characters.size() - 1)); |
这行代码定义了一个均匀分布的整数生成器 uniform,它生成范围在 0 到 characters.size() - 1 之间的整数。
1 | std::generate(id.begin(), id.end(), [&]() { return characters.at(uniform(rng)); }); |
这行代码使用 std::generate 算法,将随机选择的字符填充到 id 字符串中。generate 函数接受一个范围(由 id.begin() 和 id.end() 表示),并使用 lambda 表达式作为生成器函数。lambda 表达式使用 characters 字符串和 uniform(rng) 生成的随机索引来填充字符。
知识点
std::holds_alternative<std::string>(data)是一个类型检查的表达式,用于检查给定的变量data是否包含std::string类型的值。std::holds_alternative是 C++ 标准库中的一个函数模板,它的作用是判断给定的变量是否包含指定的类型。std::promise<void>是 C++标准库中的一个模板类,用于提供一种机制,允许一个线程在某个时间点产生一个值(或异常),并使其他线程能够等待并获取该值(或异常)。wsPromise是std::promise<void>类型的实例。这意味着它是一个用于产生void类型值的promise对象。std::promise类提供了两个主要操作:set_value()和set_exception()。通过调用set_value(),可以在promise对象上设置一个值(在这种情况下,是void类型的值),然后通过调用get_future()获得一个与该promise相关联的std::future对象,其他线程可以通过该future对象等待并获取该值。以下是一个简单的示例,展示了如何使用
std::promise<void>和相关的类来实现线程间的同步:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void worker(std::promise<void>& promise) {
// 模拟一些耗时的工作
std::this_thread::sleep_for(std::chrono::seconds(2));
// 工作完成后,设置 promise 的值
promise.set_value();
}
int main() {
std::promise<void> wsPromise;
std::future<void> wsFuture = wsPromise.get_future();
// 创建一个工作线程,并传递 promise 作为参数
std::thread workerThread(worker, std::ref(wsPromise));
// 等待工作线程完成
wsFuture.wait();
std::cout << "Worker thread finished." << std::endl;
workerThread.join();
return 0;
}在上述示例中,
worker()函数是一个工作线程执行的函数。它接受一个std::promise<void>对象作为参数,并通过调用set_value()来设置该promise对象的值。主线程使用get_future()获取与promise对象相关联的std::future对象,并使用wait()函数等待工作线程完成。一旦工作线程完成并设置了promise的值,主线程将继续执行。需要注意的是,
std::promise和std::future提供了一种线程间通信的机制,其中一个线程通过promise设置值,而另一个线程通过future等待并获取该值。std::promise类中的set_exception()函数用于在promise对象上设置一个异常,以通知与之关联的std::future对象所在的线程。当某个线程调用
set_exception()函数并提供一个异常作为参数时,与该promise对象关联的std::future对象上的等待操作将会收到该异常(通过std::future对象的get()函数或wait()函数调用时抛出)。以下是一个示例,展示了如何使用
std::promise的set_exception()函数来传递异常:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
void worker(std::promise<int>& promise) {
try {
// 模拟一些工作
std::this_thread::sleep_for(std::chrono::seconds(2));
// 抛出一个异常
throw std::runtime_error("Something went wrong.");
// 设置 promise 的值(这行代码不会执行)
promise.set_value(42);
} catch (...) {
// 捕获异常,并通过 promise 设置异常
promise.set_exception(std::current_exception());
}
}
int main() {
std::promise<int> wsPromise;
std::future<int> wsFuture = wsPromise.get_future();
// 创建一个工作线程,并传递 promise 作为参数
std::thread workerThread(worker, std::ref(wsPromise));
try {
// 等待工作线程完成
int result = wsFuture.get();
std::cout << "Worker thread finished with result: " << result << std::endl;
} catch (const std::exception& ex) {
std::cout << "Worker thread threw an exception: " << ex.what() << std::endl;
}
workerThread.join();
return 0;
}在上述示例中,
worker()函数模拟一个工作线程执行的工作。在这个例子中,工作线程抛出了一个std::runtime_error异常,然后通过set_exception()函数将异常传递给与promise对象关联的std::future对象。主线程使用get()函数获取std::future对象上的值时,如果工作线程抛出了异常,get()函数将重新抛出该异常,然后可以在主线程中捕获并处理该异常。总而言之,
set_exception()函数允许在promise对象上设置异常,以便将异常传递给与之关联的std::future对象所在的线程,从而实现线程间的异常传递和处理。std::cin.ignore()是 C++标准库中std::cin流的成员函数之一。它的作用是忽略输入流中的字符。std::cin.ignore()函数通常与std::cin结合使用,用于清除输入缓冲区中的字符,以便接下来的输入操作不会受到之前输入的影响。该函数可以在两种形式下使用:
std::cin.ignore():调用函数时不传递参数。它会忽略输入流中的下一个字符,无论是换行符、空格符还是其他字符。std::cin.ignore(n, delim):调用函数时传递两个参数。其中,n是要忽略的字符数,delim是可选的定界符(默认为换行符)。- 如果提供了
n,则会忽略输入流中的前n个字符。 - 如果同时提供了
n和delim,则会忽略输入流中的字符,直到遇到定界符delim为止。
- 如果提供了
这些函数在某些情况下很有用,例如当需要清除输入缓冲区中的残留字符时,或者在读取不同类型的数据之前需要忽略一些字符。
部分 C 语言库,在 c++文件中使用需要用
extern "C"{}的形式包裹起来,否则编译链接时会找不到库中函数的实现,例如 FFmpeg 库中的库:
1
2
3
4
5
extern "C" {
}





