> 技术文档 > Redis-plus-plus API使用指南:通用操作与数据类型接口介绍

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
  • 头文件:需要包含
    Redis-plus-plus API使用指南:通用操作与数据类型接口介绍
    参数说明
  • key:要设置值的键,std::string类型。
  • value:键对应的值,std::string类型。
  • params:用于设置额外选项,比如设置过期时间等,是sw::redis::SetParams类型对象。可以通过它调用ex(int seconds)方法设置过期时间(单位秒),px(int milliseconds)方法设置过期时间(单位毫秒),nx()表示仅当键不存在时设置,xx()表示仅当键已存在时设置。
  • sw::redis::StringView类型:就是std::string类型的const形式,只读字符串。

Redis-plus-plus API使用指南:通用操作与数据类型接口介绍

参数说明

  • 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库。
Redis-plus-plus API使用指南:通用操作与数据类型接口介绍

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:要设置的值
  • paramssw::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 类型的键值对
  • firstlast:迭代器范围,指向包含键值对的容器
  • 返回值:无

注意事项

  • mset 是原子操作,要么全部设置成功,要么全部失败
  • 会覆盖已存在的键的值,新键则直接创建
  • 相比多次调用 setmset 减少了网络交互,效率更高

示例代码

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:初始化列表,包含多个要查询的键
  • firstlast:迭代器范围,指向包含要查询键的容器
  • 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:初始化列表,包含多个要插入的元素
  • firstlast:迭代器范围,指向包含要插入元素的容器
  • 返回值: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:初始化列表,包含要监听的多个列表键
  • firstlast:迭代器范围,指向包含要监听列表键的容器
  • 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:包含多个字段-值对的初始化列表
  • firstlast:迭代器范围,指向包含字段-值对的容器
  • 返回值(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);

参数说明

  • hsethget 类似,支持批量操作
  • hmget 的返回结果通过输出迭代器写入容器,类型为 std::vector

注意事项

  • hmsethset 批量版本的别名,功能相同
  • 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:哈希表的键
  • fieldfields:要删除的字段
  • 返回值: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:要添加的多个元素(初始化列表)
  • firstlast:迭代器范围,指向要添加的元素
  • 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:集合的键
  • membermembers:要移除的元素
  • 返回值: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:要计算交集的多个集合的键
  • firstlast:迭代器范围,指向要计算交集的集合键
  • 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);

参数说明

  • sintersinterstore 类似,只是计算的是并集
  • 返回值(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
  • startstop:索引范围(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:有序集合的键
  • membermembers:要移除的元素
  • 返回值: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:有序集合的键
  • minmax:分数范围
  • params:可选参数,可设置 limitoffset
  • out:输出迭代器,用于存储结果

注意事项

  • 分数范围默认包含边界值,使用 (minmax) 可表示不包含边界
  • 可通过 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::vectorstd::liststd::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::liststd::dequestd::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::vectorstd::liststd::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(大多数标准容器) 向容器中间插入元素

使用时需根据容器特性选择合适的迭代器,避免因容器不支持对应成员函数(如vectorfront_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;}

关键注意事项

  1. 目标区间的空间
    若目标是普通数组或已初始化的容器,必须确保其大小 ≥ 源区间的元素数量,否则会溢出。
    若目标是动态容器(如 vector),可配合 std::back_inserter 自动扩容(无需提前分配空间)。

  2. 迭代器类型要求
    源区间的迭代器需满足「输入迭代器」要求(如 vector::begin()、数组指针),目标区间的迭代器需满足「输出迭代器」要求(如 vector::begin()ostream_iterator)。

  3. 与手动循环的对比
    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():获取迭代器的下一个/上一个位置
迭代器类型的兼容性

需要注意的是,这些迭代器类型是有层次结构的:

  • 随机访问迭代器 也是 双向迭代器
  • 双向迭代器 也是 前向迭代器
  • 前向迭代器 也是 输入迭代器和输出迭代器

这意味着,接受输入迭代器的算法也可以使用任何更高级的迭代器,而接受随机访问迭代器的算法则不能使用低级别的迭代器。