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

目录
- `通用 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
- 头文件:需要包含
<sw/redis++/Redis.h>
参数说明: 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
运行结果:
11111
bad 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<std::string, std::string>
类型的键值对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") });// 第二种写法: 将多个键值对组织到容器中,通过迭代器传递给msetstd::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<sw::redis::OptionalString>
注意事项:
- 结果顺序与输入键的顺序一致
- 对于不存在的键,对应的
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; // 输出: 11auto 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; // 输出: 5len = 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, cfor (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, cfor (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, bfor (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<std::string, std::string>>
类型- 若成功弹出元素:
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 eres.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; // 输出: 3std::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<sw::redis::OptionalString>
注意事项:
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<std::string, std::string>
- 返回值:无,结果通过迭代器写入容器
注意事项:
- 返回的字段-值对顺序不固定
- 对于大型哈希表,此操作可能影响性能
示例代码:
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; // 输出: trueexists = 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; // 输出: 2std::vector<std::string> fields;redis.hkeys("user", std::back_inserter(fields));// 输出: namefor (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; // 输出: 2std::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; // 输出: 2std::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; // 输出: trueis_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; // 输出: 3std::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; // 输出: 5std::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<std::string, double>
,存储成员和对应的分数
- 若容器元素类型为
- 返回值(
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<string>)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<string, double>>)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>
类型,包含成员的分数;若成员不存在,返回无效状态
注意事项:
- 分数是
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<long long>
类型,包含成员的排名(从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; // 输出: 1std::vector<std::string> members;redis.zrange("zset", 0, -1, std::back_inserter(members));// 输出: a cfor (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:40for (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);
注意事项:
- 需包含头文件
<chrono>
才能使用 - 时间字面量仅在 C++14 及以上标准中可用
- 在函数内部引入命名空间,避免全局命名空间污染
C++中迭代器类型
1. 输入迭代器(Input Iterator)
输入迭代器是最基本的迭代器类型,只能读取元素,且只能单向移动(自增)。它支持以下操作:
- 解引用(
*
):获取指向的元素(只读) - 箭头操作符(
->
):访问元素的成员 - 自增(
++
):向前移动 - 相等/不等比较(
==
,!=
)
输入迭代器通常用于从序列中读取数据,例如标准输入。
std中构造输入迭代器的函数:
std::istream_iterator
:从输入流创建输入迭代器
#include <iostream>
#include <iterator>
#include <vector>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 <iterator>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 <iterator>template< class Container >
std::back_insert_iterator<Container> back_inserter( Container& c );
-
参数说明:
c
:目标容器的引用,需支持push_back(const T&)
或push_back(T&&)
成员函数。 -
返回值:
std::back_insert_iterator<Container>
类型的迭代器,解引用并赋值时会调用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 <iterator>template< class Container >
std::front_insert_iterator<Container> front_inserter( Container& c );
参数说明: c
:目标容器的引用,需支持push_front(const T&)
或push_front(T&&)
成员函数。
返回值: std::front_insert_iterator<Container>
类型的迭代器,解引用并赋值时会调用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 <iterator>template< class Container >
std::insert_iterator<Container> inserter( Container& c, typename Container::iterator pos );
参数说明:
c
:目标容器的引用,需支持insert(iterator, const T&)
成员函数(大多数标准容器均支持)。pos
:插入位置的迭代器,元素将插入到pos
指向的元素之前。
返回值: std::insert_iterator<Container>
类型的迭代器,解引用并赋值时会调用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 <iostream>
#include <iterator>
#include <vector>
#include <algorithm>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++ 标准库<algorithm>
头文件中的一个常用算法,用于将一个序列(源)中的元素复制到另一个序列(目标)中,是迭代器模式的典型应用。
std::copy
的核心功能
从「源区间」复制元素到「目标区间」,复制的元素数量由源区间的长度决定。
- 源区间:由两个迭代器
[first, last)
指定(左闭右开,包含first
指向的元素,不包含last
指向的元素)。 - 目标区间:由一个起始迭代器
d_first
指定,需确保目标区间有足够的空间容纳复制的元素(否则会导致未定义行为)。
语法
#include <algorithm>// 复制 [first, last) 中的元素到 [d_first, d_first + (last - first))
template< class InputIt, class OutputIt >
OutputIt copy( InputIt first, InputIt last, OutputIt d_first );
- 返回值:指向目标区间中最后一个复制元素的下一个位置的迭代器。
简单示例
1. 复制数组元素到另一个数组
#include <iostream>
#include <algorithm> // 包含 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 <iostream>
#include <vector>
#include <algorithm>
#include <iterator> // 包含 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 <iostream>
#include <forward_list>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 <iostream>
#include <list>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前面插入10std::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()
:获取迭代器的下一个/上一个位置
迭代器类型的兼容性
需要注意的是,这些迭代器类型是有层次结构的:
- 随机访问迭代器 也是 双向迭代器
- 双向迭代器 也是 前向迭代器
- 前向迭代器 也是 输入迭代器和输出迭代器
这意味着,接受输入迭代器的算法也可以使用任何更高级的迭代器,而接受随机访问迭代器的算法则不能使用低级别的迭代器。