Redis-plus-plus API使用指南:通用操作与数据类型接口介绍
🍑个人主页:Jupiter. 🚀 所属专栏:Redis 欢迎大家点赞收藏评论😊
目录
-
- `通用 API`
-
-
- `连接 Redis`
- `1. get/set`
- `2. exists 方法`
- `3. del 方法`
- `4. keys 方法`
- `5. expire 方法`
- `6. ttl 方法`
- `7. type 方法`
- `8. flushall 方法`
-
- `String 类型 API`
-
-
- `1. get/set 方法`
- `2. mset 函数`
- `3. mget 方法`
- `4. append 方法`
- `5. strlen 方法`
-
- `List 类型 API`
-
-
- `1. lpush 方法`
- `2. rpush 方法`
- `3. lpop 方法`
- `4. rpop 方法`
- `5. blpop 方法`
- `6. brpop 方法`
- `7. lrange 方法`
- `8. llen 方法`
-
- `Hash 类型 API`
-
-
- `1. hset 与 hget 方法`
- `2. hmset 与 hmget 方法`
- `3. hkeys 与 hvals 方法`
- `4. hgetall 方法`
- `5. hexists 方法`
- `6. hdel 方法`
- `7. hlen 方法`
-
- `Set 类型 API`
-
-
- `1. sadd 和 smembers 方法`
- `2. srem 方法`
- `3. sismember 方法`
- `4. scard 方法`
- `5. sinter 与 sinterstore 方法`
- `6. sunion 与 sunionstore 方法`
- `7. sdiff 与 sdiffstore 方法`
-
- `ZSet 类型 API`
-
-
- `1. zadd 和 zrange 方法`
- `2. zscore 方法`
- `3. zrank 方法`
- `4. zcard 方法`
- `5. zrem 方法`
- `6. zrangebyscore 方法`
-
- `chrono时间字面量说明`
- `C++中迭代器类型`
-
-
- `1. 输入迭代器(Input Iterator)`
- `2. 输出迭代器(Output Iterator)`
- `std::copy函数`
- `3. 前向迭代器(Forward Iterator)`
- `4. 双向迭代器(Bidirectional Iterator)`
- `5. 随机访问迭代器(Random Access Iterator)`
- `迭代器类型的兼容性`
-
通用 API
连接 Redis
函数原型:
sw::redis::Redis::Redis(const std::string& uri);
参数说明:
uri
:Redis 服务器连接地址,格式为tcp://host:port
,如tcp://127.0.0.1:6379
- 若 Redis 有密码,格式为
tcp://:password@host:port
注意事项:
- 连接失败会抛出异常,建议使用 try-catch 块捕获
- 一个 Redis 对象可以执行多个命令,内部维护连接池
1. get/set
- 头文件:需要包含
参数说明: key
:要设置值的键,std::string
类型。value
:键对应的值,std::string
类型。params
:用于设置额外选项,比如设置过期时间等,是sw::redis::SetParams
类型对象。可以通过它调用ex(int seconds)
方法设置过期时间(单位秒),px(int milliseconds)
方法设置过期时间(单位毫秒),nx()
表示仅当键不存在时设置,xx()
表示仅当键已存在时设置。sw::redis::StringView
类型:就是std::string类型的const形式,只读字符串。
参数说明:
key
为要获取值的键,std::string
类型。返回值是sw::redis::OptionalString
类型,如果键不存在,OptionalString
对象处于未初始化状态。- OptionalString 是 redis-plus-plus 库定义的一个类模板(类似标准库的 std::optional),用于表示 “可能存在或不存在的字符串”。它内部包含两个核心部分:
- 一个布尔标志(标记是否有值)。
- 一个 std::string 成员(存储实际字符串,仅当有值时有效)。
它的设计目的是安全处理 “键不存在” 的场景(比如 get 命令查询不存在的键时,返回的 OptionalString 就处于 “无值” 状态)。
- OptionalString 类重载了 operator* 运算符,用于直接访问内部存储的字符串。
- OptionalString 还提供了 value() 成员函数,功能与 * 类似,用于显式获取内部字符串。
OptionalString
类型对象是不支持C++中<<运算符重载的。可以自己实现,但是更简洁的方式就是直接使用这个类型的value方法或*解引用取到类的string成员。- optional 可以隐式转成 bool 类型, 可以直接在 if 中判定. 如果是无效元素, 就是返回 false。
代码示例:
int main(){ sw::redis::Redis redis(\"tcp://127.0.0.1:6379\"); redis.set(\"key1\",\"11111\"); redis.set(\"key2\",\"22222\"); redis.set(\"key5\",\"55555\",chrono::seconds(10)); redis.set(\"key6\",\"66666\",chrono::milliseconds(6)); sw::redis::OptionalString value = redis.get(\"key1\"); if(value){ cout<<value.value()<<endl; } else{ cout<<\"bad optional access\"<<endl; } value = redis.get(\"key10\"); if(value){ cout<<value.value()<<endl; } else{ cout<<\"bad optional access\"<<endl; }}
编译报错:链接错误。是因为makefile里没有指明使用到的redis-plus-plus库。
g++ -o $@ $^ -std=c++17 /usr/local/lib/libredis++.a /lib/x86_64-linux-gnu/libhiredis.a -pthread
运行结果:
11111bad optional access
2. exists 方法
功能:检查给定的键是否存在。
函数原型:
std::size_t exists(const std::string& key);
参数说明:
key
:要检查的键,std::string
类型- 返回值:
std::size_t
类型,键存在返回1
,不存在返回0
注意事项:
- 可以传入多个键,返回存在的键的数量:
std::size_t exists(const std::string& key, const std::string&... keys);
示例代码:
int main() { sw::redis::Redis redis(\"tcp://127.0.0.1:6379\"); std::string key = \"name\"; std::size_t exists_count = redis.exists(key); if (exists_count > 0) { std::cout << \"键存在\" << std::endl; } else { std::cout << \"键不存在\" << std::endl; } return 0;}
3. del 方法
功能:删除一个或多个键。
函数原型:
std::size_t del(const std::string& key, const std::string&... keys);
参数说明:
key
:要删除的第一个键keys
:可变参数,后续要删除的键- 返回值:
std::size_t
类型,表示实际成功删除的键的数量
注意事项:
- 即使键不存在,也不会报错,只会返回 0
- 支持批量删除多个键,效率高于单个删除
示例代码:
int main() { sw::redis::Redis redis(\"tcp://127.0.0.1:6379\"); std::string key1 = \"name\"; std::string key2 = \"age\"; std::size_t deleted_count = redis.del(key1, key2); if (deleted_count > 0) { std::cout << \"成功删除 \" << deleted_count << \" 个键\" << std::endl; } else { std::cout << \"没有删除任何键\" << std::endl; } return 0;}
4. keys 方法
功能:查找所有符合给定模式的键。
函数原型:
template <typename OutputIt>void keys(const std::string& pattern, OutputIt out);
参数说明:
pattern
:匹配模式,支持通配符*
(任意字符)、?
(单个字符)、[]
(字符范围)out
:输出迭代器,用于存储匹配的键- 返回值:无,结果通过迭代器写入容器
注意事项:
- 在生产环境中,对大型数据库使用
keys
命令可能会阻塞服务器,建议使用scan
替代 - 模式匹配可能会影响性能,尽量使用精确的前缀匹配
示例代码:
int main() { sw::redis::Redis redis(\"tcp://127.0.0.1:6379\"); std::string pattern = \"key*\"; redis.set(\"key\", \"111\"); redis.set(\"key2\", \"222\"); redis.set(\"key3\", \"333\"); // 准备容器存储结果 std::vector<std::string> result; // 使用后插迭代器接收结果 auto it = std::back_inserter(result); redis.keys(pattern, it); return 0;}
5. expire 方法
功能:设置键的过期时间,单位为秒。
函数原型:
bool expire(const std::string& key, std::chrono::seconds seconds);
参数说明:
key
:要设置过期时间的键seconds
:过期时间,std::chrono::seconds
类型- 返回值:
bool
类型,设置成功返回true
,否则返回false
注意事项:
- 若键不存在,返回
false
- 可以使用
pexpire
方法设置毫秒级过期时间 - 多次调用
expire
会覆盖之前的过期时间
示例代码:
int main() { sw::redis::Redis redis(\"tcp://127.0.0.1:6379\"); std::string key = \"name\"; bool success = redis.expire(key, std::chrono::seconds(10)); if (success) { std::cout << \"设置过期时间成功\" << std::endl; } else { std::cout << \"设置过期时间失败\" << std::endl; } return 0;}
6. ttl 方法
功能:获取键剩余的过期时间,单位为秒。
函数原型:
sw::redis::OptionalInt ttl(const std::string& key);
参数说明:
key
:要查询的键- 返回值:
sw::redis::OptionalInt
类型- 键不存在:返回
nullopt
- 键存在但无过期时间:返回
-1
- 键存在且有过期时间:返回剩余秒数
- 键不存在:返回
注意事项:
- 使用
pttl
方法可以获取毫秒级剩余时间 - 对于不存在的键,返回的
OptionalInt
处于无效状态
示例代码:
int main() { sw::redis::Redis redis(\"tcp://127.0.0.1:6379\"); std::string key = \"name\"; sw::redis::OptionalInt ttl_value = redis.ttl(key); if (ttl_value) { if (*ttl_value == -1) { std::cout << \"键存在但没有设置过期时间\" << std::endl; } else { std::cout << \"键剩余过期时间: \" << *ttl_value << \" 秒\" << std::endl; } } else { std::cout << \"键不存在\" << std::endl; } return 0;}
7. type 方法
功能:获取键对应值的数据类型。
函数原型:
sw::redis::DataType type(const std::string& key);
参数说明:
key
:要查询的键- 返回值:
sw::redis::DataType
枚举类型,可能值包括:DataType::STRING
:字符串类型DataType::LIST
:列表类型DataType::SET
:集合类型DataType::ZSET
:有序集合类型DataType::HASH
:哈希类型DataType::NONE
:键不存在
注意事项:
- 对于不存在的键,返回
DataType::NONE
- 此方法仅返回主数据类型,不区分特殊类型(如 bitmap、hyperloglog 等)
示例代码:
int main() { sw::redis::Redis redis(\"tcp://127.0.0.1:6379\"); std::string key = \"name\"; sw::redis::DataType data_type = redis.type(key); if (data_type == sw::redis::DataType::STRING) { std::cout << \"键类型: 字符串\" << std::endl; } else if (data_type == sw::redis::DataType::LIST) { std::cout << \"键类型: 列表\" << std::endl; } else if (data_type == sw::redis::DataType::SET) { std::cout << \"键类型: 集合\" << std::endl; } else if (data_type == sw::redis::DataType::ZSET) { std::cout << \"键类型: 有序集合\" << std::endl; } else if (data_type == sw::redis::DataType::HASH) { std::cout << \"键类型: 哈希\" << std::endl; } else { std::cout << \"键类型: 未知或不存在\" << std::endl; } return 0;}
8. flushall 方法
功能:清空所有数据库中的所有键。
函数原型:
void flushall();
注意事项:
- 此操作不可逆,生产环境中需谨慎使用
- 可以使用
flushdb
方法只清空当前数据库
示例代码:
int main() { sw::redis::Redis redis(\"tcp://127.0.0.1:6379\"); redis.flushall(); // 清空所有数据库 std::cout << \"所有数据库已清空\" << std::endl; return 0;}
String 类型 API
1. get/set 方法
功能:set
用于设置字符串键值对,get
用于获取字符串键的值。
函数原型:
// 设置键值对void set(const std::string& key, const std::string& value);void set(const std::string& key, const std::string& value, const sw::redis::SetParams& params);// 获取键值sw::redis::OptionalString get(const std::string& key);
参数说明:
key
:要设置或获取的键value
:要设置的值params
:sw::redis::SetParams
类型,用于设置额外选项:ex(seconds)
:设置过期时间(秒)px(milliseconds)
:设置过期时间(毫秒)nx()
:仅当键不存在时设置xx()
:仅当键已存在时设置
- 返回值(
get
):sw::redis::OptionalString
类型,键存在时包含值,否则为无效状态
注意事项:
OptionalString
不支持直接输出,需使用value()
方法或解引用获取字符串set
方法会覆盖已存在的键的值SetParams
的方法可以链式调用,如SetParams().ex(10).nx()
示例代码:
int main(){ sw::redis::Redis redis(\"tcp://127.0.0.1:6379\"); // 基本设置 redis.set(\"key1\", \"11111\"); redis.set(\"key2\", \"22222\"); // 设置带过期时间的键 redis.set(\"key5\", \"55555\", std::chrono::seconds(10)); redis.set(\"key6\", \"66666\", std::chrono::milliseconds(6)); // 获取值并判断有效性 sw::redis::OptionalString value = redis.get(\"key1\"); if (value) { std::cout << value.value() << std::endl; } else { std::cout << \"bad optional access\" << std::endl; } // 获取不存在的键 value = redis.get(\"key10\"); if (value) { std::cout << value.value() << std::endl; } else { std::cout << \"bad optional access\" << std::endl; }}
2. mset 函数
功能:批量设置多个键值对。
函数原型:
// 初始化列表形式void mset(const std::initializer_list<std::pair<std::string, std::string>>& pairs);// 迭代器形式template <typename InputIt>void mset(InputIt first, InputIt last);
参数说明:
pairs
:初始化列表,包含多个std::pair
类型的键值对first
、last
:迭代器范围,指向包含键值对的容器- 返回值:无
注意事项:
mset
是原子操作,要么全部设置成功,要么全部失败- 会覆盖已存在的键的值,新键则直接创建
- 相比多次调用
set
,mset
减少了网络交互,效率更高
示例代码:
void test4(sw::redis::Redis& redis) { std::cout << \"mset\" << std::endl; redis.flushall(); // 清空所有数据,确保测试环境干净 // 第一种写法: 使用初始化列表描述多个键值对 // redis.mset({ std::make_pair(\"key1\", \"111\"), std::make_pair(\"key2\", \"222\"), std::make_pair(\"key3\", \"333\") }); // 第二种写法: 将多个键值对组织到容器中,通过迭代器传递给mset std::vector<std::pair<std::string, std::string>> keys = { {\"key1\", \"111\"}, {\"key2\", \"222\"}, {\"key3\", \"333\"} }; // 传入容器的起始和结束迭代器,批量设置键值对 redis.mset(keys.begin(), keys.end()); // 分别获取键值对,验证设置结果 auto value = redis.get(\"key1\"); if (value) { // 判断值是否存在 std::cout << \"value: \" << value.value() << std::endl; // 输出key1的值 } value = redis.get(\"key2\"); if (value) { std::cout << \"value: \" << value.value() << std::endl; // 输出key2的值 } value = redis.get(\"key3\"); if (value) { std::cout << \"value: \" << value.value() << std::endl; // 输出key3的值 }}
3. mget 方法
功能:批量获取多个键的值。
函数原型:
// 初始化列表形式template <typename OutputIt>void mget(const std::initializer_list<std::string>& keys, OutputIt out);// 迭代器形式template <typename InputIt, typename OutputIt>void mget(InputIt first, InputIt last, OutputIt out);
参数说明:
keys
:初始化列表,包含多个要查询的键first
、last
:迭代器范围,指向包含要查询键的容器out
:输出迭代器,用于存储查询结果- 返回值:无,结果通过迭代器写入容器,类型为
std::vector
注意事项:
- 结果顺序与输入键的顺序一致
- 对于不存在的键,对应的
OptionalString
为无效状态 mget
是原子操作,相比多次调用get
效率更高
示例代码:
// 辅助函数:打印容器中的元素template<typename T>inline void printContainer(const T& container) { for (const auto& elem : container) { std::cout << elem << std::endl; }}// 辅助函数:打印OptionalString容器(需处理无效值)template<typename T>inline void printContainerOptional(const T& container) { for (const auto& elem : container) { if (elem) { // 检查值是否有效 std::cout << elem.value() << std::endl; } else { std::cout << \"(键不存在)\" << std::endl; // 键不存在时的提示 } }}void test5(sw::redis::Redis& redis) { std::cout << \"mget\" << std::endl; redis.flushall(); // 清空数据,准备测试 // 先通过mset设置测试数据 std::vector<std::pair<std::string, std::string>> keys = { {\"key1\", \"111\"}, {\"key2\", \"222\"}, {\"key3\", \"333\"} }; redis.mset(keys.begin(), keys.end()); // 存储查询结果的容器,元素类型为OptionalString(可能无效) std::vector<sw::redis::OptionalString> result; // 构造后插迭代器,用于将查询结果插入容器尾部 auto it = std::back_inserter(result); // 传入要查询的键列表(包含一个不存在的key4)和迭代器 redis.mget({\"key1\", \"key2\", \"key3\", \"key4\"}, it); // 打印查询结果(key4对应位置为无效值) printContainerOptional(result);}
4. append 方法
功能:向字符串值末尾追加内容。
函数原型:
size_t append(const std::string& key, const std::string& value);
参数说明:
key
:要操作的键value
:要追加的内容- 返回值:
size_t
类型,追加后字符串的总长度
注意事项:
- 若键不存在,
append
会创建该键并设置值为要追加的内容 - 此操作是原子的,适合多线程环境下使用
示例代码:
void test_append(sw::redis::Redis& redis) { redis.set(\"str\", \"Hello\"); size_t len = redis.append(\"str\", \" World\"); std::cout << \"新长度: \" << len << std::endl; // 输出: 11 auto value = redis.get(\"str\"); if (value) { std::cout << \"值: \" << value.value() << std::endl; // 输出: Hello World }}
5. strlen 方法
功能:获取字符串值的长度。
函数原型:
size_t strlen(const std::string& key);
参数说明:
key
:要查询的键- 返回值:
size_t
类型,字符串的长度;若键不存在,返回 0
注意事项:
- 对于非字符串类型的键,会返回错误
- 长度按字节计算,对于包含多字节字符的字符串需注意
示例代码:
void test_strlen(sw::redis::Redis& redis) { redis.set(\"str\", \"Hello\"); size_t len = redis.strlen(\"str\"); std::cout << \"长度: \" << len << std::endl; // 输出: 5 len = redis.strlen(\"nonexistent\"); std::cout << \"不存在的键长度: \" << len << std::endl; // 输出: 0}
List 类型 API
1. lpush 方法
功能:向列表的左侧(头部)插入元素。
函数原型:
// 单个元素long long lpush(const std::string& key, const std::string& value);// 初始化列表long long lpush(const std::string& key, const std::initializer_list<std::string>& values);// 迭代器范围template <typename InputIt>long long lpush(const std::string& key, InputIt first, InputIt last);
参数说明:
key
:列表的键value
:要插入的单个元素values
:初始化列表,包含多个要插入的元素first
、last
:迭代器范围,指向包含要插入元素的容器- 返回值:
long long
类型,插入后列表的长度
注意事项:
- 元素按参数顺序插入到列表头部,因此最终顺序与插入顺序相反
- 若键不存在,会创建一个新的空列表并执行插入操作
- 若键对应的值不是列表类型,会返回错误
示例代码:
// 辅助函数:打印容器中的元素template<typename T>inline void printContainer(const T& container) { for (const auto& elem : container) { std::cout << elem << std::endl; }}void test1(sw::redis::Redis& redis) { std::cout << \"lpush 和 lrange\" << std::endl; redis.flushall(); // 清空数据,准备测试 // 1. 插入单个元素到列表头部 redis.lpush(\"key\", \"111\"); // 2. 插入一组元素(基于初始化列表) redis.lpush(\"key\", {\"222\", \"333\", \"444\"}); // 元素按顺序插入头部 // 3. 插入一组元素(基于迭代器) std::vector<std::string> values = {\"555\", \"666\", \"777\"}; redis.lpush(\"key\", values.begin(), values.end()); // 容器元素按顺序插入头部 // lrange:获取列表中指定范围的元素(0表示第一个元素,-1表示最后一个元素) std::vector<std::string> results; auto it = std::back_inserter(results); // 迭代器用于接收结果 redis.lrange(\"key\", 0, -1, it); // 打印列表内容(元素顺序与插入顺序相反,因每次插入到头部) printContainer(results);}
2. rpush 方法
功能:向列表的右侧(尾部)插入元素。
函数原型:
// 单个元素long long rpush(const std::string& key, const std::string& value);// 初始化列表long long rpush(const std::string& key, const std::initializer_list<std::string>& values);// 迭代器范围template <typename InputIt>long long rpush(const std::string& key, InputIt first, InputIt last);
参数说明:
- 与
lpush
相同,只是插入位置为列表尾部 - 返回值:
long long
类型,插入后列表的长度
注意事项:
- 元素按参数顺序插入到列表尾部,因此最终顺序与插入顺序相同
- 其他注意事项与
lpush
相同
示例代码:
void test_rpush(sw::redis::Redis& redis) { redis.flushall(); // 从右侧插入元素 redis.rpush(\"list\", \"a\"); redis.rpush(\"list\", {\"b\", \"c\"}); std::vector<std::string> res; redis.lrange(\"list\", 0, -1, std::back_inserter(res)); // 输出: a, b, c for (const auto& val : res) { std::cout << val << \" \"; } std::cout << std::endl;}
3. lpop 方法
功能:移除并返回列表的左侧(头部)第一个元素。
函数原型:
sw::redis::OptionalString lpop(const std::string& key);
参数说明:
key
:列表的键- 返回值:
sw::redis::OptionalString
类型,包含弹出的元素;若列表为空或不存在,返回无效状态
注意事项:
- 弹出操作会修改列表,移除被弹出的元素
- 对于空列表,返回无效的
OptionalString
示例代码:
void test_lpop(sw::redis::Redis& redis) { redis.flushall(); redis.rpush(\"list\", {\"a\", \"b\", \"c\"}); auto elem = redis.lpop(\"list\"); if (elem) { std::cout << \"弹出元素: \" << elem.value() << std::endl; // 输出: a } std::vector<std::string> res; redis.lrange(\"list\", 0, -1, std::back_inserter(res)); // 输出: b, c for (const auto& val : res) { std::cout << val << \" \"; }}
4. rpop 方法
功能:移除并返回列表的右侧(尾部)最后一个元素。
函数原型:
sw::redis::OptionalString rpop(const std::string& key);
参数说明:
- 与
lpop
相同,只是操作的是列表尾部元素 - 返回值:
sw::redis::OptionalString
类型,包含弹出的元素
注意事项:
- 与
lpop
类似,只是操作的是列表尾部
示例代码:
void test_rpop(sw::redis::Redis& redis) { redis.flushall(); redis.rpush(\"list\", {\"a\", \"b\", \"c\"}); auto elem = redis.rpop(\"list\"); if (elem) { std::cout << \"弹出元素: \" << elem.value() << std::endl; // 输出: c } std::vector<std::string> res; redis.lrange(\"list\", 0, -1, std::back_inserter(res)); // 输出: a, b for (const auto& val : res) { std::cout << val << \" \"; }}
5. blpop 方法
功能:阻塞式弹出列表左侧第一个元素,可同时监听多个列表。
函数原型:
// 初始化列表形式template <typename Rep, typename Period>sw::redis::Optional<std::pair<std::string, std::string>> blpop(const std::initializer_list<std::string>& keys, const std::chrono::duration<Rep, Period>& timeout);// 迭代器形式template <typename InputIt, typename Rep, typename Period>sw::redis::Optional<std::pair<std::string, std::string>> blpop(InputIt first, InputIt last, const std::chrono::duration<Rep, Period>& timeout);
参数说明:
keys
:初始化列表,包含要监听的多个列表键first
、last
:迭代器范围,指向包含要监听列表键的容器timeout
:超时时间,若超过此时长仍无元素,返回无效状态- 返回值:
sw::redis::Optional<std::pair>
类型- 若成功弹出元素:
pair
的第一个元素是来源列表名,第二个元素是弹出的元素 - 若超时:返回无效状态
- 若成功弹出元素:
注意事项:
- 监听多个列表时,按参数顺序检查,有元素则立即弹出第一个非空列表的元素
- 使用
std::chrono_literals
命名空间可简化超时时间写法,如10s
表示10秒 - 阻塞期间会暂停当前线程的执行,直到有元素或超时
示例代码:
void test4(sw::redis::Redis& redis) { using namespace std::chrono_literals; // 引入时间字面量,如10s // 监听多个列表,超时时间10秒 auto result = redis.blpop({\"key\", \"key2\", \"key3\"}, 10s); if (result) { // 超时前有元素弹出 std::cout << \"key:\" << result->first << std::endl; // 输出元素来源的列表名 std::cout << \"elem:\" << result->second << std::endl; // 输出弹出的元素 } else { std::cout << \"result 无效!\" << std::endl; // 超时无元素 }}
6. brpop 方法
功能:阻塞式弹出列表右侧最后一个元素,可同时监听多个列表。
函数原型:
// 与 blpop 类似,只是弹出的是列表右侧元素template <typename Rep, typename Period>sw::redis::Optional<std::pair<std::string, std::string>> brpop(const std::initializer_list<std::string>& keys, const std::chrono::duration<Rep, Period>& timeout);
参数说明:
- 与
blpop
相同,只是弹出的是列表右侧元素 - 返回值:与
blpop
相同
注意事项:
- 与
blpop
类似,只是操作的是列表右侧元素
示例代码:
void test_brpop(sw::redis::Redis& redis) { using namespace std::chrono_literals; // 启动一个线程往列表添加元素 std::thread t([&redis]() { std::this_thread::sleep_for(2s); redis.rpush(\"list1\", \"value1\"); }); // 阻塞等待右侧元素 auto result = redis.brpop({\"list1\", \"list2\"}, 5s); if (result) { std::cout << \"从 \" << result->first << \" 弹出 \" << result->second << std::endl; } else { std::cout << \"超时\" << std::endl; } t.join();}
7. lrange 方法
功能:获取列表中指定范围的元素。
函数原型:
template <typename OutputIt>void lrange(const std::string& key, long long start, long long end, OutputIt out);
参数说明:
key
:列表的键start
:起始索引(0表示第一个元素,负数表示从尾部开始计数,如-1表示最后一个元素)end
:结束索引(包含在内)out
:输出迭代器,用于存储获取的元素- 返回值:无,结果通过迭代器写入容器
注意事项:
- 若
start
大于列表长度,返回空列表 - 若
end
大于列表长度,会返回从start
到列表末尾的所有元素 - 索引从0开始,支持负数索引
示例代码:
void test_lrange(sw::redis::Redis& redis) { redis.flushall(); redis.rpush(\"list\", {\"a\", \"b\", \"c\", \"d\", \"e\"}); std::vector<std::string> res; // 获取所有元素 redis.lrange(\"list\", 0, -1, std::back_inserter(res)); // 输出: a b c d e res.clear(); // 获取索引1到3的元素 redis.lrange(\"list\", 1, 3, std::back_inserter(res)); // 输出: b c d}
8. llen 方法
功能:获取列表的长度。
函数原型:
long long llen(const std::string& key);
参数说明:
key
:列表的键- 返回值:
long long
类型,列表的长度;若键不存在,返回0;若键对应的值不是列表,返回错误
示例代码:
void test_llen(sw::redis::Redis& redis) { redis.flushall(); redis.rpush(\"list\", {\"a\", \"b\", \"c\"}); std::cout << \"列表长度: \" << redis.llen(\"list\") << std::endl; // 输出: 3 std::cout << \"不存在的列表长度: \" << redis.llen(\"nonexistent\") << std::endl; // 输出: 0}
Hash 类型 API
1. hset 与 hget 方法
功能:hset
用于向哈希表设置字段-值对,hget
用于获取哈希表中指定字段的值。
函数原型:
// hset 单个字段long long hset(const std::string& key, const std::string& field, const std::string& value);// hset 单个pair字段long long hset(const std::string& key, const std::pair<std::string, std::string>& field_value);// hset 初始化列表long long hset(const std::string& key, const std::initializer_list<std::pair<std::string, std::string>>& fields_values);// hset 迭代器范围template <typename InputIt>long long hset(const std::string& key, InputIt first, InputIt last);// hget 获取字段值sw::redis::OptionalString hget(const std::string& key, const std::string& field);
参数说明:
key
:哈希表的键field
:字段名value
:字段值fields_values
:包含多个字段-值对的初始化列表first
、last
:迭代器范围,指向包含字段-值对的容器- 返回值(
hset
):long long
类型,成功设置的新字段数量 - 返回值(
hget
):sw::redis::OptionalString
类型,包含字段的值;若字段不存在,返回无效状态
注意事项:
hset
可以设置单个或多个字段,对于已存在的字段会覆盖其值hget
只能获取单个字段的值,若需要获取多个字段值,使用hmget
- 若哈希表不存在,
hset
会创建一个新的哈希表
示例代码:
void test1(sw::redis::Redis& redis) { // 1. 设置单个字段(字段f1,值111) redis.hset(\"key\", \"f1\", \"111\"); // 2. 通过pair设置单个字段(字段f2,值222) redis.hset(\"key\", std::make_pair(\"f2\", \"222\")); // 3. 通过初始化列表设置多个字段 redis.hset(\"key\", { std::make_pair(\"f3\", \"333\"), std::make_pair(\"f4\", \"444\") }); // 4. 通过容器迭代器设置多个字段 std::vector<std::pair<std::string, std::string>> fields = { std::make_pair(\"f5\", \"555\"), std::make_pair(\"f6\", \"666\") }; redis.hset(\"key\", fields.begin(), fields.end()); // 获取字段f3的值 auto result = redis.hget(\"key\", \"f3\"); if (result) { // 字段存在 std::cout << \"result: \" << result.value() << std::endl; // 输出: 333 } else { std::cout << \"result 无效!\" << std::endl; // 字段不存在 }}
2. hmset 与 hmget 方法
功能:hmset
用于批量设置哈希表的字段-值对,hmget
用于批量获取多个字段的值。
函数原型:
// hmset 初始化列表void hmset(const std::string& key, const std::initializer_list<std::pair<std::string, std::string>>& fields_values);// hmset 迭代器范围template <typename InputIt>void hmset(const std::string& key, InputIt first, InputIt last);// hmget 初始化列表template <typename OutputIt>void hmget(const std::string& key, const std::initializer_list<std::string>& fields, OutputIt out);// hmget 迭代器范围template <typename InputIt, typename OutputIt>void hmget(const std::string& key, InputIt first, InputIt last, OutputIt out);
参数说明:
- 与
hset
和hget
类似,支持批量操作 hmget
的返回结果通过输出迭代器写入容器,类型为std::vector
注意事项:
hmset
是hset
批量版本的别名,功能相同hmget
的结果顺序与输入字段的顺序一致- 对于不存在的字段,
hmget
返回无效的OptionalString
示例代码:
void test5(sw::redis::Redis& redis) { // 1. 通过初始化列表批量设置字段-值对 redis.hmset(\"key\", { std::make_pair(\"f1\", \"111\"), std::make_pair(\"f2\", \"222\"), std::make_pair(\"f3\", \"333\") }); // 2. 通过容器迭代器批量设置字段-值对 std::vector<std::pair<std::string, std::string>> pairs = { std::make_pair(\"f4\", \"444\"), std::make_pair(\"f5\", \"555\"), std::make_pair(\"f6\", \"666\") }; redis.hmset(\"key\", pairs.begin(), pairs.end()); // 批量获取字段f1、f2、f3的值 std::vector<std::string> values; auto it = std::back_inserter(values); // 迭代器接收结果 redis.hmget(\"key\", {\"f1\", \"f2\", \"f3\"}, it); printContainer(values); // 输出: 111, 222, 333}
3. hkeys 与 hvals 方法
功能:hkeys
获取哈希表中所有字段名,hvals
获取哈希表中所有字段的值。
函数原型:
// hkeys 获取所有字段名template <typename OutputIt>void hkeys(const std::string& key, OutputIt out);// hvals 获取所有字段值template <typename OutputIt>void hvals(const std::string& key, OutputIt out);
参数说明:
key
:哈希表的键out
:输出迭代器,用于存储结果- 返回值:无,结果通过迭代器写入容器
注意事项:
- 字段名和值的返回顺序不固定,与插入顺序无关
- 对于空哈希表或不存在的键,返回空容器
示例代码:
// 辅助函数:打印容器内容template<typename T>inline void printContainer(const T& container) { for (const auto& elem : container) { std::cout << elem << std::endl; }}void test4(sw::redis::Redis& redis) { // 先设置测试数据 redis.hset(\"key\", \"f1\", \"111\"); redis.hset(\"key\", \"f2\", \"222\"); redis.hset(\"key\", \"f3\", \"333\"); // 获取所有字段名 std::vector<std::string> fields; auto itFields = std::back_inserter(fields); // 迭代器接收字段名 redis.hkeys(\"key\", itFields); printContainer(fields); // 输出: f1, f2, f3(顺序可能不同) // 获取所有字段的值 std::vector<std::string> values; auto itValues = std::back_inserter(values); // 迭代器接收值 redis.hvals(\"key\", itValues); printContainer(values); // 输出: 111, 222, 333(顺序可能不同)}
4. hgetall 方法
功能:获取哈希表中所有字段-值对。
函数原型:
template <typename OutputIt>void hgetall(const std::string& key, OutputIt out);
参数说明:
key
:哈希表的键out
:输出迭代器,用于存储结果,元素类型为std::pair
- 返回值:无,结果通过迭代器写入容器
注意事项:
- 返回的字段-值对顺序不固定
- 对于大型哈希表,此操作可能影响性能
示例代码:
void test_hgetall(sw::redis::Redis& redis) { redis.flushall(); redis.hset(\"user\", \"name\", \"Alice\"); redis.hset(\"user\", \"age\", \"30\"); redis.hset(\"user\", \"email\", \"alice@example.com\"); std::vector<std::pair<std::string, std::string>> fields_values; redis.hgetall(\"user\", std::back_inserter(fields_values)); for (const auto& p : fields_values) { std::cout << p.first << \": \" << p.second << std::endl; }}
5. hexists 方法
功能:检查哈希表中是否存在指定字段。
函数原型:
bool hexists(const std::string& key, const std::string& field);
参数说明:
key
:哈希表的键field
:要检查的字段- 返回值:
bool
类型,存在返回true
,否则返回false
注意事项:
- 若哈希表不存在,返回
false
示例代码:
void test_hexists(sw::redis::Redis& redis) { redis.flushall(); redis.hset(\"user\", \"name\", \"Alice\"); bool exists = redis.hexists(\"user\", \"name\"); std::cout << \"name 字段存在: \" << std::boolalpha << exists << std::endl; // 输出: true exists = redis.hexists(\"user\", \"age\"); std::cout << \"age 字段存在: \" << std::boolalpha << exists << std::endl; // 输出: false}
6. hdel 方法
功能:删除哈希表中的一个或多个字段。
函数原型:
long long hdel(const std::string& key, const std::string& field, const std::string&... fields);
参数说明:
key
:哈希表的键field
、fields
:要删除的字段- 返回值:
long long
类型,成功删除的字段数量
注意事项:
- 对于不存在的字段,不会计入删除数量
- 若哈希表不存在,返回 0
示例代码:
void test_hdel(sw::redis::Redis& redis) { redis.flushall(); redis.hset(\"user\", { {\"name\", \"Alice\"}, {\"age\", \"30\"}, {\"email\", \"alice@example.com\"} }); long long deleted = redis.hdel(\"user\", \"age\", \"email\"); std::cout << \"删除的字段数量: \" << deleted << std::endl; // 输出: 2 std::vector<std::string> fields; redis.hkeys(\"user\", std::back_inserter(fields)); // 输出: name for (const auto& f : fields) { std::cout << f << \" \"; }}
7. hlen 方法
功能:获取哈希表中字段的数量。
函数原型:
long long hlen(const std::string& key);
参数说明:
key
:哈希表的键- 返回值:
long long
类型,字段数量;若哈希表不存在,返回 0
示例代码:
void test_hlen(sw::redis::Redis& redis) { redis.flushall(); redis.hset(\"user\", { {\"name\", \"Alice\"}, {\"age\", \"30\"} }); std::cout << \"字段数量: \" << redis.hlen(\"user\") << std::endl; // 输出: 2 std::cout << \"不存在的哈希表字段数量: \" << redis.hlen(\"nonexistent\") << std::endl; // 输出: 0}
Set 类型 API
1. sadd 和 smembers 方法
功能:sadd
向集合添加元素,smembers
获取集合中的所有元素。
函数原型:
// sadd 单个元素long long sadd(const std::string& key, const std::string& member);// sadd 初始化列表long long sadd(const std::string& key, const std::initializer_list<std::string>& members);// sadd 迭代器范围template <typename InputIt>long long sadd(const std::string& key, InputIt first, InputIt last);// smembers 获取所有元素template <typename OutputIt>void smembers(const std::string& key, OutputIt out);
参数说明:
key
:集合的键member
:要添加的单个元素members
:要添加的多个元素(初始化列表)first
、last
:迭代器范围,指向要添加的元素out
:输出迭代器,用于存储集合中的元素- 返回值(
sadd
):long long
类型,成功添加的新元素数量(不包括已存在的元素) - 返回值(
smembers
):无,结果通过迭代器写入容器
注意事项:
- 集合中的元素是唯一的,添加已存在的元素不会改变集合
smembers
返回的元素顺序是无序的- 对于大型集合,
smembers
可能影响性能,建议使用sscan
替代
示例代码:
void test1(sw::redis::Redis& redis) { // 1. 添加单个元素 redis.sadd(\"key\", \"111\"); // 2. 通过初始化列表添加多个元素 redis.sadd(\"key\", {\"222\", \"333\", \"444\"}); // 3. 通过容器迭代器添加多个元素 std::set<std::string> elems = {\"555\", \"666\", \"777\"}; redis.sadd(\"key\", elems.begin(), elems.end()); // 获取集合所有元素(用vector存储,也可用set保持去重特性) std::vector<std::string> result; // 构造插入迭代器,指定插入位置为容器尾部(效果同back_inserter) auto it = std::inserter(result, result.end()); redis.smembers(\"key\", it); printContainer(result); // 输出: 111, 222, 333, 444, 555, 666, 777(顺序不确定)}
2. srem 方法
功能:从集合中移除一个或多个元素。
函数原型:
// 单个元素long long srem(const std::string& key, const std::string& member);// 初始化列表long long srem(const std::string& key, const std::initializer_list<std::string>& members);// 迭代器范围template <typename InputIt>long long srem(const std::string& key, InputIt first, InputIt last);
参数说明:
key
:集合的键member
、members
:要移除的元素- 返回值:
long long
类型,成功移除的元素数量(不包括不存在的元素)
注意事项:
- 移除不存在的元素不会报错,只会返回 0
- 若集合不存在,返回 0
示例代码:
void test_srem(sw::redis::Redis& redis) { redis.flushall(); redis.sadd(\"set\", {\"a\", \"b\", \"c\", \"d\"}); long long removed = redis.srem(\"set\", \"b\", \"d\"); std::cout << \"移除的元素数量: \" << removed << std::endl; // 输出: 2 std::vector<std::string> members; redis.smembers(\"set\", std::back_inserter(members)); // 输出: a c(顺序不确定) for (const auto& m : members) { std::cout << m << \" \"; }}
3. sismember 方法
功能:检查元素是否是集合的成员。
函数原型:
bool sismember(const std::string& key, const std::string& member);
参数说明:
key
:集合的键member
:要检查的元素- 返回值:
bool
类型,是成员返回true
,否则返回false
注意事项:
- 若集合不存在,返回
false
示例代码:
void test_sismember(sw::redis::Redis& redis) { redis.flushall(); redis.sadd(\"set\", {\"a\", \"b\", \"c\"}); bool is_member = redis.sismember(\"set\", \"b\"); std::cout << \"b 是成员: \" << std::boolalpha << is_member << std::endl; // 输出: true is_member = redis.sismember(\"set\", \"d\"); std::cout << \"d 是成员: \" << std::boolalpha << is_member << std::endl; // 输出: false}
4. scard 方法
功能:获取集合中元素的数量。
函数原型:
long long scard(const std::string& key);
参数说明:
key
:集合的键- 返回值:
long long
类型,元素数量;若集合不存在,返回 0
示例代码:
void test_scard(sw::redis::Redis& redis) { redis.flushall(); redis.sadd(\"set\", {\"a\", \"b\", \"c\"}); std::cout << \"集合元素数量: \" << redis.scard(\"set\") << std::endl; // 输出: 3 std::cout << \"不存在的集合元素数量: \" << redis.scard(\"nonexistent\") << std::endl; // 输出: 0}
5. sinter 与 sinterstore 方法
功能:sinter
计算多个集合的交集,sinterstore
计算多个集合的交集并存储到新集合。
函数原型:
// sinter 初始化列表template <typename OutputIt>void sinter(const std::initializer_list<std::string>& keys, OutputIt out);// sinter 迭代器范围template <typename InputIt, typename OutputIt>void sinter(InputIt first, InputIt last, OutputIt out);// sinterstore 初始化列表long long sinterstore(const std::string& dest, const std::initializer_list<std::string>& keys);// sinterstore 迭代器范围template <typename InputIt>long long sinterstore(const std::string& dest, InputIt first, InputIt last);
参数说明:
keys
:要计算交集的多个集合的键first
、last
:迭代器范围,指向要计算交集的集合键out
:输出迭代器,用于存储交集结果dest
:存储交集结果的新集合的键- 返回值(
sinterstore
):long long
类型,交集中的元素数量
注意事项:
- 若输入的集合中有一个为空,交集也为空
- 若某个集合不存在,视为空集
sinterstore
会覆盖dest
集合(如果已存在)
示例代码:
void test5(sw::redis::Redis& redis) { // 初始化两个集合 redis.sadd(\"key1\", {\"111\", \"222\", \"333\"}); redis.sadd(\"key2\", {\"111\", \"222\", \"444\"}); // 计算交集(111, 222) std::set<std::string> result; auto it = std::inserter(result, result.end()); // 接收交集结果 redis.sinter({\"key1\", \"key2\"}, it); printContainer(result); // 输出: 111, 222}void test6(sw::redis::Redis& redis) { // 初始化两个集合 redis.sadd(\"key1\", {\"111\", \"222\", \"333\"}); redis.sadd(\"key2\", {\"111\", \"222\", \"444\"}); // 计算交集并存储到key3,返回元素个数 long long len = redis.sinterstore(\"key3\", {\"key1\", \"key2\"}); std::cout << \"len: \" << len << std::endl; // 输出: 2 // 验证存储结果 std::set<std::string> result; auto it = std::inserter(result, result.end()); redis.smembers(\"key3\", it); printContainer(result); // 输出: 111, 222}
6. sunion 与 sunionstore 方法
功能:sunion
计算多个集合的并集,sunionstore
计算多个集合的并集并存储到新集合。
函数原型:
// sunion 初始化列表template <typename OutputIt>void sunion(const std::initializer_list<std::string>& keys, OutputIt out);// sunion 迭代器范围template <typename InputIt, typename OutputIt>void sunion(InputIt first, InputIt last, OutputIt out);// sunionstore 初始化列表long long sunionstore(const std::string& dest, const std::initializer_list<std::string>& keys);// sunionstore 迭代器范围template <typename InputIt>long long sunionstore(const std::string& dest, InputIt first, InputIt last);
参数说明:
- 与
sinter
和sinterstore
类似,只是计算的是并集 - 返回值(
sunionstore
):long long
类型,并集中的元素数量
注意事项:
- 并集包含所有集合中的所有元素,重复元素只保留一个
sunionstore
会覆盖dest
集合(如果已存在)
示例代码:
void test_sunion(sw::redis::Redis& redis) { redis.flushall(); redis.sadd(\"set1\", {\"a\", \"b\", \"c\"}); redis.sadd(\"set2\", {\"c\", \"d\", \"e\"}); std::vector<std::string> result; redis.sunion({\"set1\", \"set2\"}, std::back_inserter(result)); // 输出: a b c d e(顺序不确定) for (const auto& val : result) { std::cout << val << \" \"; } std::cout << std::endl;}void test_sunionstore(sw::redis::Redis& redis) { redis.flushall(); redis.sadd(\"set1\", {\"a\", \"b\", \"c\"}); redis.sadd(\"set2\", {\"c\", \"d\", \"e\"}); long long len = redis.sunionstore(\"set3\", {\"set1\", \"set2\"}); std::cout << \"并集元素数量: \" << len << std::endl; // 输出: 5 std::vector<std::string> result; redis.smembers(\"set3\", std::back_inserter(result)); // 输出: a b c d e(顺序不确定) for (const auto& val : result) { std::cout << val << \" \"; }}
7. sdiff 与 sdiffstore 方法
功能:sdiff
计算多个集合的差集,sdiffstore
计算多个集合的差集并存储到新集合。
函数原型:
// sdiff 初始化列表template <typename OutputIt>void sdiff(const std::initializer_list<std::string>& keys, OutputIt out);// sdiff 迭代器范围template <typename InputIt, typename OutputIt>void sdiff(InputIt first, InputIt last, OutputIt out);// sdiffstore 初始化列表long long sdiffstore(const std::string& dest, const std::initializer_list<std::string>& keys);// sdiffstore 迭代器范围template <typename InputIt>long long sdiffstore(const std::string& dest, InputIt first, InputIt last);
参数说明:
- 与
sinter
类似,计算的是差集(存在于第一个集合但不存在于其他集合的元素) - 返回值(
sdiffstore
):long long
类型,差集中的元素数量
示例代码:
void test_sdiff(sw::redis::Redis& redis) { redis.flushall(); redis.sadd(\"set1\", {\"a\", \"b\", \"c\", \"d\"}); redis.sadd(\"set2\", {\"c\", \"d\", \"e\", \"f\"}); std::vector<std::string> result; redis.sdiff({\"set1\", \"set2\"}, std::back_inserter(result)); // 输出: a b(顺序不确定) for (const auto& val : result) { std::cout << val << \" \"; }}
ZSet 类型 API
1. zadd 和 zrange 方法
功能:zadd
向有序集合添加元素(包含分数),zrange
按索引范围获取有序集合的元素。
函数原型:
// zadd 单个元素long long zadd(const std::string& key, double score, const std::string& member);// zadd 单个pair元素long long zadd(const std::string& key, const std::pair<double, std::string>& score_member);// zadd 初始化列表long long zadd(const std::string& key, const std::initializer_list<std::pair<double, std::string>>& score_members);// zadd 迭代器范围template <typename InputIt>long long zadd(const std::string& key, InputIt first, InputIt last);// zrange 获取元素(仅成员)template <typename OutputIt>void zrange(const std::string& key, long long start, long long stop, OutputIt out);// zrange 获取元素(成员+分数)template <typename OutputIt>void zrange(const std::string& key, long long start, long long stop, OutputIt out);
参数说明:
key
:有序集合的键score
:元素的分数(用于排序)member
:元素的值score_member
:包含分数和成员的pair
start
、stop
:索引范围(0表示第一个元素,-1表示最后一个元素)out
:输出迭代器,用于存储结果- 若容器元素类型为
std::string
,仅存储成员 - 若容器元素类型为
std::pair
,存储成员和对应的分数
- 若容器元素类型为
- 返回值(
zadd
):long long
类型,成功添加的新元素数量
注意事项:
- 有序集合中的元素是唯一的,但分数可以相同
- 若元素已存在,
zadd
会更新其分数 zrange
按分数升序返回元素,使用zrevrange
可按分数降序返回
示例代码:
void test1(sw::redis::Redis& redis) { // 1. 添加单个元素(成员\"吕布\",分数99) redis.zadd(\"key\", \"吕布\", 99); // 2. 通过初始化列表添加多个元素 redis.zadd(\"key\", { std::make_pair(\"赵云\", 98), std::make_pair(\"典韦\", 97) }); // 3. 通过容器迭代器添加多个元素 std::vector<std::pair<std::string, double>> members = { std::make_pair(\"关羽\", 95), std::make_pair(\"张飞\", 93) }; redis.zadd(\"key\", members.begin(), members.end()); // zrange用法1:仅获取成员(容器为vector) std::vector<std::string> memberResults; auto it = std::back_inserter(memberResults); redis.zrange(\"key\", 0, -1, it); // 0到-1表示所有元素(按分数升序) printContainer(memberResults); // 输出: 张飞(93), 关羽(95), 典韦(97), 赵云(98), 吕布(99) // zrange用法2:获取成员+分数(容器为vector<pair>) std::vector<std::pair<std::string, double>> membersWithScore; auto it2 = std::back_inserter(membersWithScore); redis.zrange(\"key\", 0, -1, it2); // 遍历输出(每个元素是pair) for (const auto& p : membersWithScore) { std::cout << p.first << \":\" << p.second << std::endl; }}
2. zscore 方法
功能:获取有序集合中指定成员的分数。
函数原型:
sw::redis::Optional<double> zscore(const std::string& key, const std::string& member);
参数说明:
key
:有序集合的键member
:要查询的成员- 返回值:
sw::redis::Optional
类型,包含成员的分数;若成员不存在,返回无效状态
注意事项:
- 分数是
double
类型,可以是整数或小数 - 若有序集合不存在,返回无效状态
示例代码:
void test4(sw::redis::Redis& redis) { std::cout << \"zscore\" << std::endl; redis.flushall(); // 初始化有序集合 redis.zadd(\"key\", \"zhangsan\", 90); redis.zadd(\"key\", \"lisi\", 91); redis.zadd(\"key\", \"wangwu\", 92); redis.zadd(\"key\", \"zhaoliu\", 93); // 获取\"zhangsan\"的分数 auto score = redis.zscore(\"key\", \"zhangsan\"); if (score) { // 成员存在 std::cout << \"score: \" << score.value() << std::endl; // 输出: 90 } else { std::cout << \"score 无效\" << std::endl; // 成员不存在 }}
3. zrank 方法
功能:获取有序集合中指定成员的排名(按分数升序)。
函数原型:
sw::redis::Optional<long long> zrank(const std::string& key, const std::string& member);
参数说明:
key
:有序集合的键member
:要查询的成员- 返回值:
sw::redis::Optional
类型,包含成员的排名(从0开始);若成员不存在,返回无效状态
注意事项:
- 排名按分数升序计算,分数最低的成员排名为0
- 使用
zrevrank
可获取按分数降序的排名
示例代码:
void test5(sw::redis::Redis& redis) { // 初始化有序集合 redis.zadd(\"key\", \"zhangsan\", 90); redis.zadd(\"key\", \"lisi\", 91); redis.zadd(\"key\", \"wangwu\", 92); redis.zadd(\"key\", \"zhaoliu\", 93); // 获取\"zhaoliu\"的排名(分数最高,排名3) auto rank = redis.zrank(\"key\", \"zhaoliu\"); if (rank) { // 成员存在 std::cout << \"rank: \" << rank.value() << std::endl; // 输出: 3 } else { std::cout << \"rank 无效\" << std::endl; // 成员不存在 }}
4. zcard 方法
功能:获取有序集合中元素的数量。
函数原型:
long long zcard(const std::string& key);
参数说明:
key
:有序集合的键- 返回值:
long long
类型,元素数量;若有序集合不存在,返回0
示例代码:
void test_zcard(sw::redis::Redis& redis) { redis.flushall(); redis.zadd(\"zset\", { {\"a\", 10}, {\"b\", 20}, {\"c\", 30} }); std::cout << \"有序集合元素数量: \" << redis.zcard(\"zset\") << std::endl; // 输出: 3}
5. zrem 方法
功能:从有序集合中移除一个或多个元素。
函数原型:
// 单个元素long long zrem(const std::string& key, const std::string& member);// 初始化列表long long zrem(const std::string& key, const std::initializer_list<std::string>& members);// 迭代器范围template <typename InputIt>long long zrem(const std::string& key, InputIt first, InputIt last);
参数说明:
key
:有序集合的键member
、members
:要移除的元素- 返回值:
long long
类型,成功移除的元素数量
示例代码:
void test_zrem(sw::redis::Redis& redis) { redis.flushall(); redis.zadd(\"zset\", { {\"a\", 10}, {\"b\", 20}, {\"c\", 30} }); long long removed = redis.zrem(\"zset\", \"b\"); std::cout << \"移除的元素数量: \" << removed << std::endl; // 输出: 1 std::vector<std::string> members; redis.zrange(\"zset\", 0, -1, std::back_inserter(members)); // 输出: a c for (const auto& m : members) { std::cout << m << \" \"; }}
6. zrangebyscore 方法
功能:获取有序集合中分数在指定范围内的元素。
函数原型:
// 仅获取成员template <typename OutputIt>void zrangebyscore(const std::string& key, double min, double max, OutputIt out);// 获取成员+分数template <typename OutputIt>void zrangebyscore(const std::string& key, double min, double max, OutputIt out);// 带参数的版本template <typename OutputIt>void zrangebyscore(const std::string& key, double min, double max, const sw::redis::ZRangeByScoreParams& params, OutputIt out);
参数说明:
key
:有序集合的键min
、max
:分数范围params
:可选参数,可设置limit
、offset
等out
:输出迭代器,用于存储结果
注意事项:
- 分数范围默认包含边界值,使用
(min
或max)
可表示不包含边界 - 可通过
ZRangeByScoreParams
设置返回结果的偏移量和数量
示例代码:
void test_zrangebyscore(sw::redis::Redis& redis) { redis.flushall(); redis.zadd(\"zset\", { {\"a\", 10}, {\"b\", 20}, {\"c\", 30}, {\"d\", 40}, {\"e\", 50} }); // 获取分数在20到40之间的元素 std::vector<std::pair<std::string, double>> result; redis.zrangebyscore(\"zset\", 20, 40, std::back_inserter(result)); // 输出: b:20 c:30 d:40 for (const auto& p : result) { std::cout << p.first << \":\" << p.second << \" \"; }}
chrono时间字面量说明
std::chrono_literals
std::chrono_literals
是 C++14 引入的命名空间,提供时间单位字面量,简化时间间隔的表示:
s
:秒(对应std::chrono::seconds
)ms
:毫秒(对应std::chrono::milliseconds
)us
:微秒(对应std::chrono::microseconds
)ns
:纳秒(对应std::chrono::nanoseconds
)min
:分钟(对应std::chrono::minutes
)h
:小时(对应std::chrono::hours
)
使用方法:
通过 using namespace std::chrono_literals;
引入命名空间后,可直接在数值后添加后缀表示时间:
// 10s 表示10秒,作为blpop的超时时间参数auto result = redis.blpop({\"key\", \"key2\", \"key3\"}, 10s);
注意事项:
- 需包含头文件
才能使用
- 时间字面量仅在 C++14 及以上标准中可用
- 在函数内部引入命名空间,避免全局命名空间污染
C++中迭代器类型
1. 输入迭代器(Input Iterator)
输入迭代器是最基本的迭代器类型,只能读取元素,且只能单向移动(自增)。它支持以下操作:
- 解引用(
*
):获取指向的元素(只读) - 箭头操作符(
->
):访问元素的成员 - 自增(
++
):向前移动 - 相等/不等比较(
==
,!=
)
输入迭代器通常用于从序列中读取数据,例如标准输入。
std中构造输入迭代器的函数:
std::istream_iterator
:从输入流创建输入迭代器
#include #include #include int main() { // 使用istream_iterator从标准输入读取整数 std::cout << \"请输入一些整数(以非整数结束):\" << std::endl; std::istream_iterator<int> input_iter(std::cin); std::istream_iterator<int> end_of_stream; // 流结束迭代器 std::vector<int> numbers; // 使用输入迭代器读取数据 while (input_iter != end_of_stream) { numbers.push_back(*input_iter); ++input_iter; } return 0;}
2. 输出迭代器(Output Iterator)
输出迭代器与输入迭代器相反,它只能用于写入元素,同样只能单向移动。它支持以下操作:
- 解引用(
*
):获取指向的位置(只写) - 自增(
++
):向前移动
输出迭代器通常用于向序列中写入数据,例如标准输出。
std中构造输出迭代器的函数:
std::ostream_iterator
:创建输出到流的迭代器std::back_inserter
:创建插入到容器尾部的迭代器std::front_inserter
:创建插入到容器头部的迭代器std::inserter
:创建插入到容器指定位置的迭代器
1. std::ostream_iterator
功能:创建一个输出迭代器,将元素写入到指定的输出流(如std::cout
、文件流等),常用于直接输出元素。
函数原型:
#include template< class T, class CharT = char, class Traits = std::char_traits<CharT> >class ostream_iterator : public std::output_iterator_tag {public: // 构造函数:绑定输出流和分隔符 ostream_iterator( std::basic_ostream<CharT, Traits>& os, const CharT* delim ); ostream_iterator( std::basic_ostream<CharT, Traits>& os ); // 无分隔符版本 };
参数说明:
os
:要写入的输出流(如std::cout
)。delim
:可选参数,元素之间的分隔符(如空格、逗号),类型为const CharT*
(通常传入字符串字面量)。
示例:
std::ostream_iterator<int> out_it(std::cout, \" \"); // 输出到控制台,元素间用空格分隔*out_it = 10; // 输出 \"10 \"++out_it;*out_it = 20; // 输出 \"20 \"(最终显示 \"10 20 \")
2. std::back_inserter
- 功能:创建一个输出迭代器,通过容器的
push_back()
成员函数向容器尾部插入元素,适用于支持push_back()
的容器(如std::vector
、std::list
、std::deque
)。
函数原型:
#include template< class Container >std::back_insert_iterator<Container> back_inserter( Container& c );
-
参数说明:
c
:目标容器的引用,需支持push_back(const T&)
或push_back(T&&)
成员函数。 -
返回值:
std::back_insert_iterator
类型的迭代器,解引用并赋值时会调用c.push_back(值)
。
示例:
std::vector<int> vec;auto it = std::back_inserter(vec); // 创建尾部插入迭代器*it = 1; // 等价于 vec.push_back(1)++it;*it = 2; // 等价于 vec.push_back(2) → vec 变为 [1, 2]
3. std::front_inserter
- 功能:创建一个输出迭代器,通过容器的
push_front()
成员函数向容器头部插入元素,适用于支持push_front()
的容器(如std::list
、std::deque
,std::vector
不支持)。
函数原型:
#include template< class Container >std::front_insert_iterator<Container> front_inserter( Container& c );
参数说明: c
:目标容器的引用,需支持push_front(const T&)
或push_front(T&&)
成员函数。
返回值: std::front_insert_iterator
类型的迭代器,解引用并赋值时会调用c.push_front(值)
。
示例:
std::list<int> lst;auto it = std::front_inserter(lst); // 创建头部插入迭代器*it = 1; // 等价于 lst.push_front(1) → lst: [1]++it;*it = 2; // 等价于 lst.push_front(2) → lst: [2, 1]
std::inserter
- 功能:创建一个输出迭代器,通过容器的
insert()
成员函数向容器指定位置插入元素,插入后原位置元素后移,适用于大多数有序容器(如std::vector
、std::list
、std::set
)。
函数原型:
#include template< class Container >std::insert_iterator<Container> inserter( Container& c, typename Container::iterator pos );
参数说明:
c
:目标容器的引用,需支持insert(iterator, const T&)
成员函数(大多数标准容器均支持)。pos
:插入位置的迭代器,元素将插入到pos
指向的元素之前。
返回值: std::insert_iterator
类型的迭代器,解引用并赋值时会调用c.insert(pos, 值)
,且插入后迭代器会自动更新位置(保证后续插入在新元素之后)。
示例:
std::vector<int> vec = {1, 3};auto it = std::inserter(vec, vec.begin() + 1); // 在索引1的位置(元素3前)插入*it = 2; // 等价于 vec.insert(vec.begin() + 1, 2) → vec 变为 [1, 2, 3]++it;*it = 4; // 插入到上一个插入位置之后 → vec 变为 [1, 2, 4, 3]
总结
- 这四个函数均返回输出迭代器,核心区别在于元素的写入/插入方式:
ostream_iterator
back_inserter
push_back
)push_back
(如vector
)front_inserter
push_front
)push_front
(如list
)inserter
insert
)insert
(大多数标准容器)使用时需根据容器特性选择合适的迭代器,避免因容器不支持对应成员函数(如vector
用front_inserter
)导致编译错误。
#include #include #include #include int main() { std::vector<int> numbers = {1, 2, 3, 4, 5}; // 使用ostream_iterator输出到标准输出 std::cout << \"输出到控制台:\"; std::copy(numbers.begin(), numbers.end(), std::ostream_iterator<int>(std::cout, \" \")); std::cout << std::endl; // 使用back_inserter向容器尾部插入元素 std::vector<int> squared_numbers; for_each(numbers.begin(), numbers.end(), [&](int n) { squared_numbers.push_back(n * n); }); std::cout << \"平方后的数字:\"; std::copy(squared_numbers.begin(), squared_numbers.end(), std::ostream_iterator<int>(std::cout, \" \")); std::cout << std::endl; return 0;}
std::copy函数
std::copy
是 C++ 标准库头文件中的一个常用算法,用于将一个序列(源)中的元素复制到另一个序列(目标)中,是迭代器模式的典型应用。
std::copy
的核心功能
从「源区间」复制元素到「目标区间」,复制的元素数量由源区间的长度决定。
- 源区间:由两个迭代器
[first, last)
指定(左闭右开,包含first
指向的元素,不包含last
指向的元素)。 - 目标区间:由一个起始迭代器
d_first
指定,需确保目标区间有足够的空间容纳复制的元素(否则会导致未定义行为)。
语法
#include // 复制 [first, last) 中的元素到 [d_first, d_first + (last - first))template< class InputIt, class OutputIt >OutputIt copy( InputIt first, InputIt last, OutputIt d_first );
- 返回值:指向目标区间中最后一个复制元素的下一个位置的迭代器。
简单示例
1. 复制数组元素到另一个数组
#include #include // 包含 std::copyint main() { int source[] = {1, 2, 3, 4, 5}; int dest[5]; // 目标数组,需提前分配足够空间 // 复制 source[0..4] 到 dest[0..4] std::copy(std::begin(source), std::end(source), std::begin(dest)); // 打印结果 for (int num : dest) { std::cout << num << \" \"; // 输出:1 2 3 4 5 } return 0;}
2. 复制容器元素到另一个容器
#include #include #include #include // 包含 ostream_iteratorint main() { std::vector<int> source = {10, 20, 30}; std::vector<int> dest; // 为目标容器预留空间(可选,但能提高效率) dest.reserve(source.size()); // 复制 source 到 dest(使用 back_inserter 自动插入尾部) std::copy(source.begin(), source.end(), std::back_inserter(dest)); // 直接复制到控制台(使用 ostream_iterator) std::cout << \"复制到控制台:\"; std::copy(dest.begin(), dest.end(), std::ostream_iterator<int>(std::cout, \" \")); // 输出:复制到控制台:10 20 30 return 0;}
关键注意事项
-
目标区间的空间:
若目标是普通数组或已初始化的容器,必须确保其大小 ≥ 源区间的元素数量,否则会溢出。
若目标是动态容器(如vector
),可配合std::back_inserter
自动扩容(无需提前分配空间)。 -
迭代器类型要求:
源区间的迭代器需满足「输入迭代器」要求(如vector::begin()
、数组指针),目标区间的迭代器需满足「输出迭代器」要求(如vector::begin()
、ostream_iterator
)。 -
与手动循环的对比:
std::copy
本质上等价于手动循环复制(如下),但代码更简洁,且由标准库优化,效率相同:// 等价于 std::copy(first, last, d_first)while (first != last) { *d_first = *first; ++first; ++d_first;}
常见应用场景
- 容器间的元素复制(如
vector
复制到list
)。 - 配合
ostream_iterator
直接输出容器内容到控制台或文件。 - 配合
back_inserter
向容器动态添加元素(无需手动push_back
)。
std::copy
是 C++ 中处理元素复制的基础工具,掌握它能简化代码并提高可读性。
3. 前向迭代器(Forward Iterator)
-
前向迭代器结合了输入迭代器和输出迭代器的功能,既可以读取也可以写入元素,并且可以在序列中向前移动。与输入/输出迭代器不同,前向迭代器可以多次遍历同一个序列。
-
前向迭代器支持输入和输出迭代器的所有操作,还可以被复制和赋值。
std中构造前向迭代器的函数:
std::forward_list::begin()
/std::forward_list::end()
:获取forward_list的前向迭代器std::unordered_set::begin()
/std::unordered_set::end()
:获取unordered_set的前向迭代器std::unordered_map::begin()
/std::unordered_map::end()
:获取unordered_map的前向迭代器
#include #include int main() { std::forward_list<int> numbers = {1, 2, 3, 4, 5}; std::cout << \"初始列表:\"; for (auto it = numbers.begin(); it != numbers.end(); ++it) { std::cout << *it << \" \"; } std::cout << std::endl; // 使用前向迭代器修改元素 for (auto it = numbers.begin(); it != numbers.end(); ++it) { *it *= 2; // 将每个元素乘以2 } std::cout << \"修改后的列表:\"; for (auto it = numbers.begin(); it != numbers.end(); ++it) { std::cout << *it << \" \"; } std::cout << std::endl; return 0;}
4. 双向迭代器(Bidirectional Iterator)
-
双向迭代器在前向迭代器的基础上增加了向后移动的能力(自减操作)。它支持前向迭代器的所有操作,还增加了:
-
自减(
--
):向后移动 -
双向迭代器可以在序列中向前和向后移动,适用于需要双向遍历的场景。
std中构造双向迭代器的函数:
std::list::begin()
/std::list::end()
:获取list的双向迭代器std::list::rbegin()
/std::list::rend()
:获取list的反向双向迭代器std::set::begin()
/std::set::end()
:获取set的双向迭代器std::map::begin()
/std::map::end()
:获取map的双向迭代器
#include #include int main() { std::list<int> numbers = {1, 2, 3, 4, 5}; std::cout << \"正向遍历:\"; for (auto it = numbers.begin(); it != numbers.end(); ++it) { std::cout << *it << \" \"; } std::cout << std::endl; std::cout << \"反向遍历:\"; for (auto it = numbers.end(); it != numbers.begin(); ) { --it; std::cout << *it << \" \"; } std::cout << std::endl; // 在列表中间插入元素 auto it = numbers.begin(); std::advance(it, 2); // 移动到第三个元素 numbers.insert(it, 10); // 在3前面插入10 std::cout << \"插入后的列表:\"; for (int num : numbers) { std::cout << num << \" \"; } std::cout << std::endl; return 0;}
5. 随机访问迭代器(Random Access Iterator)
- 随机访问迭代器是功能最强大的迭代器类型,它支持双向迭代器的所有操作,还可以进行随机访问(直接跳转到序列中的任意位置)。
随机访问迭代器增加的操作:
- 加减整数(
+
,-
,+=
,-=
):移动指定数量的元素 - 下标操作(
[]
):访问指定位置的元素 - 比较操作(
<
,>
,<=
,>=
):比较迭代器位置
std中构造随机访问迭代器的函数:
std::vector::begin()
/std::vector::end()
:获取vector的随机访问迭代器std::deque::begin()
/std::deque::end()
:获取deque的随机访问迭代器std::array::begin()
/std::array::end()
:获取array的随机访问迭代器std::pointer_iterator
:将指针包装成随机访问迭代器std::next()
/std::prev()
:获取迭代器的下一个/上一个位置
迭代器类型的兼容性
需要注意的是,这些迭代器类型是有层次结构的:
- 随机访问迭代器 也是 双向迭代器
- 双向迭代器 也是 前向迭代器
- 前向迭代器 也是 输入迭代器和输出迭代器
这意味着,接受输入迭代器的算法也可以使用任何更高级的迭代器,而接受随机访问迭代器的算法则不能使用低级别的迭代器。