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" {
}