1.bind函数的用法:
对一个函数绑定一个,或多个固定的参数
:
print(const std::string &str,......);
print("hello",.......);
或者
auto func =bind(print,"hello",......);
func();
此时,两者的结果一致,原理是bind函数可以依据一个函数的地址为其绑定n个固定的参数,并返回一个新的函数(这里取名为func()),当执行func()时就相当于执行print("hello",.....);
除此之外,我们还可以为func()手动添加参数(非固定参数):
void print(int a, int b, int c, int d, int e) {
std::cout << a << " " << b << " " << c << " " << d << " " << e << std::endl;
}
auto func = std::bind(print, 1, 2, 3, std::placeholders::_1, std::placeholders::_2);
func(4, 5); // 输出:1 2 3 4 5
这里的placeholders表示预留一个参数位,后面更一个::_1表示这是第一个参数,std::placeholders::_2则表示预留第二个手动输入的参数,
所以func(4,5)中的4和5就会去代替std::placeholders::_1和std::placeholders::_2
当然我们也可以直接这样写std::bind(print, 1, 2, 3, 4,5);
2.定时器(timerfd)
1️⃣创建定时器
#include <sys/timerfd.h>
int timerfd_create(int clockid, int flags);
clockid - 时钟类型
| 时钟类型 | 说明 |
|---|---|
CLOCK_REALTIME |
系统实时时钟,受 NTP 调整影响,如果系统时间变化,就会影响到定时器 |
CLOCK_MONOTONIC |
单调递增时钟,不受系统时间调整影响(推荐),记录系统启动时间 |
CLOCK_BOOTTIME |
包含系统休眠时间的单调时钟 |
CLOCK_REALTIME_ALARM |
需要 root 权限,可唤醒系统 |
CLOCK_BOOTTIME_ALARM |
需要 root 权限,可唤醒系统 |
flags - 标志位
| 标志 | 说明 |
|---|---|
0 |
默认行为 |
TFD_NONBLOCK |
设置为非阻塞模式 |
TFD_CLOEXEC |
执行 exec 时自动关闭文件描述符 |
返回值
-
成功:返回文件描述符
-
失败:返回 -1,设置 errno
定时器超时时,内核会自动向 timerfd 文件描述符(tfd)写入一个 8 字节的数字,表示超时次数。
int tfd = timerfd_create(CLOCK_MONOTONIC, 0);
// 设置定时器:每 1 秒超时一次
timerfd_settime(tfd, 0, &new_val, NULL);
// 关键:当超时发生时,内核自动向 tfd 写入 8 字节数据
uint64_t expirations;
read(tfd, &expirations, sizeof(uint64_t)); // 阻塞等待超时
用户程序 内核
│ │
├─ timerfd_create() ───→│ 创建定时器对象
│ │
├─ timerfd_settime() ──→│ 启动定时器(1秒)
│ │
│ │ ⏰ 1秒后超时!
│ │ 自动向 tfd 写入: 0x0001
│←───── read() 返回 ────┤ (写入8字节数据)
│ expirations = 1 │
│ │
│ │ ⏰ 又过1秒,再次超时
│ │ 自动向 tfd 写入: 0x0002
│←───── read() 返回 ────┤ (累计超时2次)
│ expirations = 2 │
2️⃣启动或停止定时器
#include <sys/timerfd.h>
int timerfd_settime(int fd, int flags,
const struct itimerspec *new_value,
struct itimerspec *old_value);
参数详解
1. fd - 文件描述符
-
来源 :由
timerfd_create()创建的定时器文件描述符 -
作用:指定要操作的定时器
int tfd = timerfd_create(CLOCK_REALTIME, 0);
timerfd_settime(tfd, ...);
2. flags - 标志位
决定 new_value 中的 it_value 如何解释:
| 标志 | 含义 |
|---|---|
0 |
相对时间(相对于当前时间) |
TFD_TIMER_ABSTIME |
绝对时间(从 Epoch 1970-01-01 开始) |
TFD_TIMER_CANCEL_ON_SET |
当系统时间被调整时取消定时器(需配合 ABSTIME) |
示例:
// 相对时间:3秒后超时
timerfd_settime(fd, 0, &new_val, NULL);
// 绝对时间:在 2025-01-01 00:00:00 超时
timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_val, NULL);
3. new_value - 新定时器值(输入)
指向 struct itimerspec,设置定时器的超时时间和间隔。
struct itimerspec {
struct timespec it_interval; // 周期性间隔(0=单次)
struct timespec it_value; // 首次超时时间
};
struct timespec {
time_t tv_sec; // 秒
long tv_nsec; // 纳秒 (0-999999999)
};
配置示例:
struct itimerspec new_val;
// 单次定时器:3秒后超时一次
new_val.it_value.tv_sec = 3;
new_val.it_value.tv_nsec = 0;
new_val.it_interval.tv_sec = 0;
new_val.it_interval.tv_nsec = 0;
// 周期性定时器:2秒后开始,每隔1秒超时一次
new_val.it_value.tv_sec = 2; // 首次 2秒
new_val.it_value.tv_nsec = 0;
new_val.it_interval.tv_sec = 1; // 之后每 1秒
new_val.it_interval.tv_nsec = 0;
// 停止定时器
new_val.it_value.tv_sec = 0;
new_val.it_value.tv_nsec = 0;
4. old_value - 旧定时器值(输出)
-
作用:返回之前的定时器设置(可为 NULL)
-
注意 :如果
old_value非 NULL,函数会写入之前的配置struct itimerspec old_val;
timerfd_settime(fd, 0, &new_val, &old_val);
// old_val 现在保存修改前的定时器设置
返回值
| 返回值 | 含义 |
|---|---|
0 |
成功 |
-1 |
失败,设置 errno |
3.正则表达式
对一个字符串,提取,匹配或替换里面的数据,就是正则表达式
bool std::regex_match(
const std::string& str, // 目标字符串
std::smatch& m, // 匹配结果(存储提取的数据)
const std::regex& re // 正则表达式对象
);
三种正则表达式:
| 函数 | 必需参数 | 可选参数 | 返回值 |
|---|---|---|---|
regex_match |
字符串, 正则 | 匹配结果 | bool |
regex_search |
字符串, 正则 | 匹配结果 | bool |
regex_replace |
字符串, 正则, 替换串 | 标志 | string |
1️⃣std::smatch类型
std::smatch类型是类似于数组的容器,在正则表达式中,他不会保存整个原字符串,但会保存原字符串的匹配结果的索引信息
原字符串 text:
┌─────────────────────────────────────────┐
│ H e l l o w o r l d , w e l c o m e │
└─────────────────────────────────────────┘
↑ ↑
0 6
matches 内部:
┌─────────────────────────────────────────┐
│ 指向原字符串的指针 ──────────┐ │
│ matches[0]: {pos:0, len:11} │ (完整匹配 "Hello world")
│ matches[1]: {pos:0, len:5} │ (第1组 "Hello")
│ matches[2]: {pos:6, len:5} │ (第2组 "world")
└─────────────────────────────────────────┘
2️⃣re
re是正则表达式的匹配规则,是一个regex类型的变量,
std::regex re(R"(\$(\d+)\.(\d+))");
核心其实还是字符串的匹配
一、核心规则速查表
| 规则类型 | 符号 | 含义 | 示例 | 匹配 |
|---|---|---|---|---|
| 普通字符 | 字母数字 | 匹配自身 | abc |
"abc" |
| 通配符 | . |
匹配任意单个字符(除\r\n) | a.c |
"abc", "aXc" |
| 转义 | \\ |
把特殊字符变成普通字符 | \\. \\? |
"." "?" |
| 字符集 | [...] |
匹配其中任意一个字符 | [aeiou] |
"a","e","i","o","u" |
| 排除字符 | [^...] |
匹配除这些外的字符 | [^0-9] |
非数字 |
| 范围 | - |
字符范围 | [a-z] |
小写字母 |
需要双反斜杠查询?的原因,c++中有预定义字符,当你写出\?是,c++首先会想到\d,\D这样的预定义字符,但是没有\?所以会报错,当你\\后C++会认为是\(转义字符),此时\?就是字符?了
二、重复/量词规则
| 符号 | 含义 | 示例 | 匹配 |
|---|---|---|---|
* |
0次或多次 | a* |
"", "a", "aa" |
+ |
1次或多次 | a+ |
"a", "aa" |
? |
0次或1次 | a? |
"", "a" |
{n} |
恰好n次 | a{3} |
"aaa" |
{n,} |
至少n次 | a{2,} |
"aa", "aaa" |
{n,m} |
n到m次 | a{2,4} |
"aa","aaa","aaaa" |
三、位置锚点规则
| 符号 | 含义 | 示例 | 匹配 |
|---|---|---|---|
^ |
行的开头 | ^Hello |
"Hello..." |
$ |
行的结尾 | world$ |
"...world" |
\b |
单词边界 | \bcat\b |
"cat" 单独出现 |
\B |
非单词边界 | \Bcat |
"scat" 中的 "cat" |
四、预定义字符类
| 符号 | 含义 | 等价于 | 示例 |
|---|---|---|---|
\d |
数字 | [0-9] |
\d{11} 匹配11位数字 |
\D |
非数字 | [^0-9] |
|
\w |
单词字符 | [a-zA-Z0-9_] |
\w+ 匹配单词 |
\W |
非单词字符 | [^a-zA-Z0-9_] |
|
\s |
空白字符 | [ \t\n\r\f\v] |
|
\S |
非空白字符 | [^ \t\n\r\f\v] |
五、分组和捕获
| 符号 | 含义 | 示例 |
|---|---|---|
( ) |
分组捕获(提取) | (\d{4})-(\d{2}) 提取年月 |
(?: ) |
非捕获分组 | (?:abc) 只匹配不捕获 |
\1, \2 |
反向引用 | (.)\1 匹配重复字符如"aa" |
| ` | ` | 或 |
4.日志宏
| 符号 | 含义 | 示例 |
| ... | 不定参(表示参数数量和内容不限定) | LOG(a,b,...) |
| VA_ARGS | 用来被不定参替换(或者接受不定参) | fprintf(VA_ARGS) |
| ## | 表示没有不定参的时候可以忽略__VA_ARGS__ | fprintf(##VA_ARGS) |
| \ | 宏要求内容必须始终处于同一行,\表示一个该行和下一行处于同一行(相当于英语中的换行继续写) | do{\ }while() |
|---|
5.setsockopt()
setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR, (void*)&val, sizeof(int));
这 5 个参数分别控制:操作哪个 socket 、哪一层协议 、哪个选项 、设置什么值 、值多长。
参数逐个解释
| 参数 | 值 | 含义 |
|---|---|---|
_sockfd |
socket 文件描述符 | 要操作的 socket |
SOL_SOCKET |
套接字层 | 设置的是 socket 本身的选项(而非 TCP/UDP 层) |
SO_REUSEADDR |
地址重用选项 | 具体要设置哪个属性 |
(void*)&val |
指向 val 的指针 | 设置val的值(1=开启,0=关闭),开启或关闭socket的选项 |
sizeof(int) |
4 字节 | 告诉内核 val 有多大 |
第二个参数
// 常用层级
SOL_SOCKET // socket 层(通用选项)
IPPROTO_TCP // TCP 层(TCP 专用选项)
IPPROTO_IP // IP 层(IP 专用选项)
6.int fcntl();
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */);
参数说明
| 参数 | 含义 |
|---|---|
fd |
要操作的文件描述符(socket、文件等) |
cmd |
要执行的命令(做什么操作) |
... |
可选参数,取决于 cmd |
常用命令(cmd)
| 命令 | 作用 | 是否需要第3个参数 |
|---|---|---|
F_GETFL |
获取文件状态标志 | 不需要 |
F_SETFL |
设置文件状态标志 | 需要(新标志) |
F_GETFD |
获取文件描述符标志 | 不需要 |
F_SETFD |
设置文件描述符标志 | 需要 |
F_DUPFD |
复制文件描述符 | 需要 |
1. F_GETFL - 获取文件状态标志
int flag = fcntl(fd, F_GETFL, 0);
// 返回当前的文件状态标志
常用标志位:
| 标志 | 含义 |
|---|---|
O_RDONLY |
只读 |
O_WRONLY |
只写 |
O_RDWR |
读写 |
O_NONBLOCK |
非阻塞模式 |
O_APPEND |
追加模式 |
O_SYNC |
同步写入 |
2. F_SETFL - 设置文件状态标志
int ret = fcntl(fd, F_SETFL, new_flags);
// 设置新的文件状态标志