
目录
通用 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") });
// 第二种写法: 将多个键值对组织到容器中,通过迭代器传递给mset
std::vector<std::pair<std::string, std::string>> keys = {
{"key1", "111"},
{"key2", "222"},
{"key3", "333"}
};
// 传入容器的起始和结束迭代器,批量设置键值对
redis.mset(keys.begin(), keys.end());
// 分别获取键值对,验证设置结果
auto value = redis.get("key1");
if (value) { // 判断值是否存在
std::cout << "value: " << value.value() << std::endl; // 输出key1的值
}
value = redis.get("key2");
if (value) {
std::cout << "value: " << value.value() << std::endl; // 输出key2的值
}
value = redis.get("key3");
if (value) {
std::cout << "value: " << value.value() << std::endl; // 输出key3的值
}
}
3. mget 方法
功能:批量获取多个键的值。
函数原型:
// 初始化列表形式
template <typename OutputIt>
void mget(const std::initializer_list<std::string>& keys, OutputIt out);
// 迭代器形式
template <typename InputIt, typename OutputIt>
void mget(InputIt first, InputIt last, OutputIt out);
参数说明:
keys
:初始化列表,包含多个要查询的键first
、last
:迭代器范围,指向包含要查询键的容器out
:输出迭代器,用于存储查询结果- 返回值:无,结果通过迭代器写入容器,类型为
std::vector<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; // 输出: 11
auto value = redis.get("str");
if (value) {
std::cout << "值: " << value.value() << std::endl; // 输出: Hello World
}
}
5. strlen 方法
功能:获取字符串值的长度。
函数原型:
size_t strlen(const std::string& key);
参数说明:
key
:要查询的键- 返回值:
size_t
类型,字符串的长度;若键不存在,返回 0
注意事项:
- 对于非字符串类型的键,会返回错误
- 长度按字节计算,对于包含多字节字符的字符串需注意
示例代码:
void test_strlen(sw::redis::Redis& redis) {
redis.set("str", "Hello");
size_t len = redis.strlen("str");
std::cout << "长度: " << len << std::endl; // 输出: 5
len = redis.strlen("nonexistent");
std::cout << "不存在的键长度: " << len << std::endl; // 输出: 0
}
List 类型 API
1. lpush 方法
功能:向列表的左侧(头部)插入元素。
函数原型:
// 单个元素
long long lpush(const std::string& key, const std::string& value);
// 初始化列表
long long lpush(const std::string& key, const std::initializer_list<std::string>& values);
// 迭代器范围
template <typename InputIt>
long long lpush(const std::string& key, InputIt first, InputIt last);
参数说明:
key
:列表的键value
:要插入的单个元素values
:初始化列表,包含多个要插入的元素first
、last
:迭代器范围,指向包含要插入元素的容器- 返回值:
long long
类型,插入后列表的长度
注意事项:
- 元素按参数顺序插入到列表头部,因此最终顺序与插入顺序相反
- 若键不存在,会创建一个新的空列表并执行插入操作
- 若键对应的值不是列表类型,会返回错误
示例代码:
// 辅助函数:打印容器中的元素
template<typename T>
inline void printContainer(const T& container) {
for (const auto& elem : container) {
std::cout << elem << std::endl;
}
}
void test1(sw::redis::Redis& redis) {
std::cout << "lpush 和 lrange" << std::endl;
redis.flushall(); // 清空数据,准备测试
// 1. 插入单个元素到列表头部
redis.lpush("key", "111");
// 2. 插入一组元素(基于初始化列表)
redis.lpush("key", {"222", "333", "444"}); // 元素按顺序插入头部
// 3. 插入一组元素(基于迭代器)
std::vector<std::string> values = {"555", "666", "777"};
redis.lpush("key", values.begin(), values.end()); // 容器元素按顺序插入头部
// lrange:获取列表中指定范围的元素(0表示第一个元素,-1表示最后一个元素)
std::vector<std::string> results;
auto it = std::back_inserter(results); // 迭代器用于接收结果
redis.lrange("key", 0, -1, it);
// 打印列表内容(元素顺序与插入顺序相反,因每次插入到头部)
printContainer(results);
}
2. rpush 方法
功能:向列表的右侧(尾部)插入元素。
函数原型:
// 单个元素
long long rpush(const std::string& key, const std::string& value);
// 初始化列表
long long rpush(const std::string& key, const std::initializer_list<std::string>& values);
// 迭代器范围
template <typename InputIt>
long long rpush(const std::string& key, InputIt first, InputIt last);
参数说明:
- 与
lpush
相同,只是插入位置为列表尾部 - 返回值:
long long
类型,插入后列表的长度
注意事项:
- 元素按参数顺序插入到列表尾部,因此最终顺序与插入顺序相同
- 其他注意事项与
lpush
相同
示例代码:
void test_rpush(sw::redis::Redis& redis) {
redis.flushall();
// 从右侧插入元素
redis.rpush("list", "a");
redis.rpush("list", {"b", "c"});
std::vector<std::string> res;
redis.lrange("list", 0, -1, std::back_inserter(res));
// 输出: a, b, c
for (const auto& val : res) {
std::cout << val << " ";
}
std::cout << std::endl;
}
3. lpop 方法
功能:移除并返回列表的左侧(头部)第一个元素。
函数原型:
sw::redis::OptionalString lpop(const std::string& key);
参数说明:
key
:列表的键- 返回值:
sw::redis::OptionalString
类型,包含弹出的元素;若列表为空或不存在,返回无效状态
注意事项:
- 弹出操作会修改列表,移除被弹出的元素
- 对于空列表,返回无效的
OptionalString
示例代码:
void test_lpop(sw::redis::Redis& redis) {
redis.flushall();
redis.rpush("list", {"a", "b", "c"});
auto elem = redis.lpop("list");
if (elem) {
std::cout << "弹出元素: " << elem.value() << std::endl; // 输出: a
}
std::vector<std::string> res;
redis.lrange("list", 0, -1, std::back_inserter(res));
// 输出: b, c
for (const auto& val : res) {
std::cout << val << " ";
}
}
4. rpop 方法
功能:移除并返回列表的右侧(尾部)最后一个元素。
函数原型:
sw::redis::OptionalString rpop(const std::string& key);
参数说明:
- 与
lpop
相同,只是操作的是列表尾部元素 - 返回值:
sw::redis::OptionalString
类型,包含弹出的元素
注意事项:
- 与
lpop
类似,只是操作的是列表尾部
示例代码:
void test_rpop(sw::redis::Redis& redis) {
redis.flushall();
redis.rpush("list", {"a", "b", "c"});
auto elem = redis.rpop("list");
if (elem) {
std::cout << "弹出元素: " << elem.value() << std::endl; // 输出: c
}
std::vector<std::string> res;
redis.lrange("list", 0, -1, std::back_inserter(res));
// 输出: a, b
for (const auto& val : res) {
std::cout << val << " ";
}
}
5. blpop 方法
功能:阻塞式弹出列表左侧第一个元素,可同时监听多个列表。
函数原型:
// 初始化列表形式
template <typename Rep, typename Period>
sw::redis::Optional<std::pair<std::string, std::string>>
blpop(const std::initializer_list<std::string>& keys,
const std::chrono::duration<Rep, Period>& timeout);
// 迭代器形式
template <typename InputIt, typename Rep, typename Period>
sw::redis::Optional<std::pair<std::string, std::string>>
blpop(InputIt first, InputIt last,
const std::chrono::duration<Rep, Period>& timeout);
参数说明:
keys
:初始化列表,包含要监听的多个列表键first
、last
:迭代器范围,指向包含要监听列表键的容器timeout
:超时时间,若超过此时长仍无元素,返回无效状态- 返回值:
sw::redis::Optional<std::pair<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 e
res.clear();
// 获取索引1到3的元素
redis.lrange("list", 1, 3, std::back_inserter(res));
// 输出: b c d
}
8. llen 方法
功能:获取列表的长度。
函数原型:
long long llen(const std::string& key);
参数说明:
key
:列表的键- 返回值:
long long
类型,列表的长度;若键不存在,返回0;若键对应的值不是列表,返回错误
示例代码:
void test_llen(sw::redis::Redis& redis) {
redis.flushall();
redis.rpush("list", {"a", "b", "c"});
std::cout << "列表长度: " << redis.llen("list") << std::endl; // 输出: 3
std::cout << "不存在的列表长度: " << redis.llen("nonexistent") << std::endl; // 输出: 0
}
Hash 类型 API
1. hset 与 hget 方法
功能:hset
用于向哈希表设置字段-值对,hget
用于获取哈希表中指定字段的值。
函数原型:
// hset 单个字段
long long hset(const std::string& key, const std::string& field, const std::string& value);
// hset 单个pair字段
long long hset(const std::string& key, const std::pair<std::string, std::string>& field_value);
// hset 初始化列表
long long hset(const std::string& key, const std::initializer_list<std::pair<std::string, std::string>>& fields_values);
// hset 迭代器范围
template <typename InputIt>
long long hset(const std::string& key, InputIt first, InputIt last);
// hget 获取字段值
sw::redis::OptionalString hget(const std::string& key, const std::string& field);
参数说明:
key
:哈希表的键field
:字段名value
:字段值fields_values
:包含多个字段-值对的初始化列表first
、last
:迭代器范围,指向包含字段-值对的容器- 返回值(
hset
):long long
类型,成功设置的新字段数量 - 返回值(
hget
):sw::redis::OptionalString
类型,包含字段的值;若字段不存在,返回无效状态
注意事项:
hset
可以设置单个或多个字段,对于已存在的字段会覆盖其值hget
只能获取单个字段的值,若需要获取多个字段值,使用hmget
- 若哈希表不存在,
hset
会创建一个新的哈希表
示例代码:
void test1(sw::redis::Redis& redis) {
// 1. 设置单个字段(字段f1,值111)
redis.hset("key", "f1", "111");
// 2. 通过pair设置单个字段(字段f2,值222)
redis.hset("key", std::make_pair("f2", "222"));
// 3. 通过初始化列表设置多个字段
redis.hset("key", {
std::make_pair("f3", "333"),
std::make_pair("f4", "444")
});
// 4. 通过容器迭代器设置多个字段
std::vector<std::pair<std::string, std::string>> fields = {
std::make_pair("f5", "555"),
std::make_pair("f6", "666")
};
redis.hset("key", fields.begin(), fields.end());
// 获取字段f3的值
auto result = redis.hget("key", "f3");
if (result) { // 字段存在
std::cout << "result: " << result.value() << std::endl; // 输出: 333
} else {
std::cout << "result 无效!" << std::endl; // 字段不存在
}
}
2. hmset 与 hmget 方法
功能:hmset
用于批量设置哈希表的字段-值对,hmget
用于批量获取多个字段的值。
函数原型:
// hmset 初始化列表
void hmset(const std::string& key, const std::initializer_list<std::pair<std::string, std::string>>& fields_values);
// hmset 迭代器范围
template <typename InputIt>
void hmset(const std::string& key, InputIt first, InputIt last);
// hmget 初始化列表
template <typename OutputIt>
void hmget(const std::string& key, const std::initializer_list<std::string>& fields, OutputIt out);
// hmget 迭代器范围
template <typename InputIt, typename OutputIt>
void hmget(const std::string& key, InputIt first, InputIt last, OutputIt out);
参数说明:
- 与
hset
和hget
类似,支持批量操作 hmget
的返回结果通过输出迭代器写入容器,类型为std::vector<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; // 输出: true
exists = redis.hexists("user", "age");
std::cout << "age 字段存在: " << std::boolalpha << exists << std::endl; // 输出: false
}
6. hdel 方法
功能:删除哈希表中的一个或多个字段。
函数原型:
long long hdel(const std::string& key, const std::string& field, const std::string&... fields);
参数说明:
key
:哈希表的键field
、fields
:要删除的字段- 返回值:
long long
类型,成功删除的字段数量
注意事项:
- 对于不存在的字段,不会计入删除数量
- 若哈希表不存在,返回 0
示例代码:
void test_hdel(sw::redis::Redis& redis) {
redis.flushall();
redis.hset("user", {
{"name", "Alice"},
{"age", "30"},
{"email", "alice@example.com"}
});
long long deleted = redis.hdel("user", "age", "email");
std::cout << "删除的字段数量: " << deleted << std::endl; // 输出: 2
std::vector<std::string> fields;
redis.hkeys("user", std::back_inserter(fields));
// 输出: name
for (const auto& f : fields) {
std::cout << f << " ";
}
}
7. hlen 方法
功能:获取哈希表中字段的数量。
函数原型:
long long hlen(const std::string& key);
参数说明:
key
:哈希表的键- 返回值:
long long
类型,字段数量;若哈希表不存在,返回 0
示例代码:
void test_hlen(sw::redis::Redis& redis) {
redis.flushall();
redis.hset("user", {
{"name", "Alice"},
{"age", "30"}
});
std::cout << "字段数量: " << redis.hlen("user") << std::endl; // 输出: 2
std::cout << "不存在的哈希表字段数量: " << redis.hlen("nonexistent") << std::endl; // 输出: 0
}
Set 类型 API
1. sadd 和 smembers 方法
功能:sadd
向集合添加元素,smembers
获取集合中的所有元素。
函数原型:
// sadd 单个元素
long long sadd(const std::string& key, const std::string& member);
// sadd 初始化列表
long long sadd(const std::string& key, const std::initializer_list<std::string>& members);
// sadd 迭代器范围
template <typename InputIt>
long long sadd(const std::string& key, InputIt first, InputIt last);
// smembers 获取所有元素
template <typename OutputIt>
void smembers(const std::string& key, OutputIt out);
参数说明:
key
:集合的键member
:要添加的单个元素members
:要添加的多个元素(初始化列表)first
、last
:迭代器范围,指向要添加的元素out
:输出迭代器,用于存储集合中的元素- 返回值(
sadd
):long long
类型,成功添加的新元素数量(不包括已存在的元素) - 返回值(
smembers
):无,结果通过迭代器写入容器
注意事项:
- 集合中的元素是唯一的,添加已存在的元素不会改变集合
smembers
返回的元素顺序是无序的- 对于大型集合,
smembers
可能影响性能,建议使用sscan
替代
示例代码:
void test1(sw::redis::Redis& redis) {
// 1. 添加单个元素
redis.sadd("key", "111");
// 2. 通过初始化列表添加多个元素
redis.sadd("key", {"222", "333", "444"});
// 3. 通过容器迭代器添加多个元素
std::set<std::string> elems = {"555", "666", "777"};
redis.sadd("key", elems.begin(), elems.end());
// 获取集合所有元素(用vector存储,也可用set保持去重特性)
std::vector<std::string> result;
// 构造插入迭代器,指定插入位置为容器尾部(效果同back_inserter)
auto it = std::inserter(result, result.end());
redis.smembers("key", it);
printContainer(result); // 输出: 111, 222, 333, 444, 555, 666, 777(顺序不确定)
}
2. srem 方法
功能:从集合中移除一个或多个元素。
函数原型:
// 单个元素
long long srem(const std::string& key, const std::string& member);
// 初始化列表
long long srem(const std::string& key, const std::initializer_list<std::string>& members);
// 迭代器范围
template <typename InputIt>
long long srem(const std::string& key, InputIt first, InputIt last);
参数说明:
key
:集合的键member
、members
:要移除的元素- 返回值:
long long
类型,成功移除的元素数量(不包括不存在的元素)
注意事项:
- 移除不存在的元素不会报错,只会返回 0
- 若集合不存在,返回 0
示例代码:
void test_srem(sw::redis::Redis& redis) {
redis.flushall();
redis.sadd("set", {"a", "b", "c", "d"});
long long removed = redis.srem("set", "b", "d");
std::cout << "移除的元素数量: " << removed << std::endl; // 输出: 2
std::vector<std::string> members;
redis.smembers("set", std::back_inserter(members));
// 输出: a c(顺序不确定)
for (const auto& m : members) {
std::cout << m << " ";
}
}
3. sismember 方法
功能:检查元素是否是集合的成员。
函数原型:
bool sismember(const std::string& key, const std::string& member);
参数说明:
key
:集合的键member
:要检查的元素- 返回值:
bool
类型,是成员返回true
,否则返回false
注意事项:
- 若集合不存在,返回
false
示例代码:
void test_sismember(sw::redis::Redis& redis) {
redis.flushall();
redis.sadd("set", {"a", "b", "c"});
bool is_member = redis.sismember("set", "b");
std::cout << "b 是成员: " << std::boolalpha << is_member << std::endl; // 输出: true
is_member = redis.sismember("set", "d");
std::cout << "d 是成员: " << std::boolalpha << is_member << std::endl; // 输出: false
}
4. scard 方法
功能:获取集合中元素的数量。
函数原型:
long long scard(const std::string& key);
参数说明:
key
:集合的键- 返回值:
long long
类型,元素数量;若集合不存在,返回 0
示例代码:
void test_scard(sw::redis::Redis& redis) {
redis.flushall();
redis.sadd("set", {"a", "b", "c"});
std::cout << "集合元素数量: " << redis.scard("set") << std::endl; // 输出: 3
std::cout << "不存在的集合元素数量: " << redis.scard("nonexistent") << std::endl; // 输出: 0
}
5. sinter 与 sinterstore 方法
功能:sinter
计算多个集合的交集,sinterstore
计算多个集合的交集并存储到新集合。
函数原型:
// sinter 初始化列表
template <typename OutputIt>
void sinter(const std::initializer_list<std::string>& keys, OutputIt out);
// sinter 迭代器范围
template <typename InputIt, typename OutputIt>
void sinter(InputIt first, InputIt last, OutputIt out);
// sinterstore 初始化列表
long long sinterstore(const std::string& dest, const std::initializer_list<std::string>& keys);
// sinterstore 迭代器范围
template <typename InputIt>
long long sinterstore(const std::string& dest, InputIt first, InputIt last);
参数说明:
keys
:要计算交集的多个集合的键first
、last
:迭代器范围,指向要计算交集的集合键out
:输出迭代器,用于存储交集结果dest
:存储交集结果的新集合的键- 返回值(
sinterstore
):long long
类型,交集中的元素数量
注意事项:
- 若输入的集合中有一个为空,交集也为空
- 若某个集合不存在,视为空集
sinterstore
会覆盖dest
集合(如果已存在)
示例代码:
void test5(sw::redis::Redis& redis) {
// 初始化两个集合
redis.sadd("key1", {"111", "222", "333"});
redis.sadd("key2", {"111", "222", "444"});
// 计算交集(111, 222)
std::set<std::string> result;
auto it = std::inserter(result, result.end()); // 接收交集结果
redis.sinter({"key1", "key2"}, it);
printContainer(result); // 输出: 111, 222
}
void test6(sw::redis::Redis& redis) {
// 初始化两个集合
redis.sadd("key1", {"111", "222", "333"});
redis.sadd("key2", {"111", "222", "444"});
// 计算交集并存储到key3,返回元素个数
long long len = redis.sinterstore("key3", {"key1", "key2"});
std::cout << "len: " << len << std::endl; // 输出: 2
// 验证存储结果
std::set<std::string> result;
auto it = std::inserter(result, result.end());
redis.smembers("key3", it);
printContainer(result); // 输出: 111, 222
}
6. sunion 与 sunionstore 方法
功能:sunion
计算多个集合的并集,sunionstore
计算多个集合的并集并存储到新集合。
函数原型:
// sunion 初始化列表
template <typename OutputIt>
void sunion(const std::initializer_list<std::string>& keys, OutputIt out);
// sunion 迭代器范围
template <typename InputIt, typename OutputIt>
void sunion(InputIt first, InputIt last, OutputIt out);
// sunionstore 初始化列表
long long sunionstore(const std::string& dest, const std::initializer_list<std::string>& keys);
// sunionstore 迭代器范围
template <typename InputIt>
long long sunionstore(const std::string& dest, InputIt first, InputIt last);
参数说明:
- 与
sinter
和sinterstore
类似,只是计算的是并集 - 返回值(
sunionstore
):long long
类型,并集中的元素数量
注意事项:
- 并集包含所有集合中的所有元素,重复元素只保留一个
sunionstore
会覆盖dest
集合(如果已存在)
示例代码:
void test_sunion(sw::redis::Redis& redis) {
redis.flushall();
redis.sadd("set1", {"a", "b", "c"});
redis.sadd("set2", {"c", "d", "e"});
std::vector<std::string> result;
redis.sunion({"set1", "set2"}, std::back_inserter(result));
// 输出: a b c d e(顺序不确定)
for (const auto& val : result) {
std::cout << val << " ";
}
std::cout << std::endl;
}
void test_sunionstore(sw::redis::Redis& redis) {
redis.flushall();
redis.sadd("set1", {"a", "b", "c"});
redis.sadd("set2", {"c", "d", "e"});
long long len = redis.sunionstore("set3", {"set1", "set2"});
std::cout << "并集元素数量: " << len << std::endl; // 输出: 5
std::vector<std::string> result;
redis.smembers("set3", std::back_inserter(result));
// 输出: a b c d e(顺序不确定)
for (const auto& val : result) {
std::cout << val << " ";
}
}
7. sdiff 与 sdiffstore 方法
功能:sdiff
计算多个集合的差集,sdiffstore
计算多个集合的差集并存储到新集合。
函数原型:
// sdiff 初始化列表
template <typename OutputIt>
void sdiff(const std::initializer_list<std::string>& keys, OutputIt out);
// sdiff 迭代器范围
template <typename InputIt, typename OutputIt>
void sdiff(InputIt first, InputIt last, OutputIt out);
// sdiffstore 初始化列表
long long sdiffstore(const std::string& dest, const std::initializer_list<std::string>& keys);
// sdiffstore 迭代器范围
template <typename InputIt>
long long sdiffstore(const std::string& dest, InputIt first, InputIt last);
参数说明:
- 与
sinter
类似,计算的是差集(存在于第一个集合但不存在于其他集合的元素) - 返回值(
sdiffstore
):long long
类型,差集中的元素数量
示例代码:
void test_sdiff(sw::redis::Redis& redis) {
redis.flushall();
redis.sadd("set1", {"a", "b", "c", "d"});
redis.sadd("set2", {"c", "d", "e", "f"});
std::vector<std::string> result;
redis.sdiff({"set1", "set2"}, std::back_inserter(result));
// 输出: a b(顺序不确定)
for (const auto& val : result) {
std::cout << val << " ";
}
}
ZSet 类型 API
1. zadd 和 zrange 方法
功能:zadd
向有序集合添加元素(包含分数),zrange
按索引范围获取有序集合的元素。
函数原型:
// zadd 单个元素
long long zadd(const std::string& key, double score, const std::string& member);
// zadd 单个pair元素
long long zadd(const std::string& key, const std::pair<double, std::string>& score_member);
// zadd 初始化列表
long long zadd(const std::string& key, const std::initializer_list<std::pair<double, std::string>>& score_members);
// zadd 迭代器范围
template <typename InputIt>
long long zadd(const std::string& key, InputIt first, InputIt last);
// zrange 获取元素(仅成员)
template <typename OutputIt>
void zrange(const std::string& key, long long start, long long stop, OutputIt out);
// zrange 获取元素(成员+分数)
template <typename OutputIt>
void zrange(const std::string& key, long long start, long long stop, OutputIt out);
参数说明:
key
:有序集合的键score
:元素的分数(用于排序)member
:元素的值score_member
:包含分数和成员的pair
start
、stop
:索引范围(0表示第一个元素,-1表示最后一个元素)out
:输出迭代器,用于存储结果- 若容器元素类型为
std::string
,仅存储成员 - 若容器元素类型为
std::pair<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; // 输出: 1
std::vector<std::string> members;
redis.zrange("zset", 0, -1, std::back_inserter(members));
// 输出: a c
for (const auto& m : members) {
std::cout << m << " ";
}
}
6. zrangebyscore 方法
功能:获取有序集合中分数在指定范围内的元素。
函数原型:
// 仅获取成员
template <typename OutputIt>
void zrangebyscore(const std::string& key, double min, double max, OutputIt out);
// 获取成员+分数
template <typename OutputIt>
void zrangebyscore(const std::string& key, double min, double max, OutputIt out);
// 带参数的版本
template <typename OutputIt>
void zrangebyscore(const std::string& key, double min, double max,
const sw::redis::ZRangeByScoreParams& params, OutputIt out);
参数说明:
key
:有序集合的键min
、max
:分数范围params
:可选参数,可设置limit
、offset
等out
:输出迭代器,用于存储结果
注意事项:
- 分数范围默认包含边界值,使用
(min
或max)
可表示不包含边界 - 可通过
ZRangeByScoreParams
设置返回结果的偏移量和数量
示例代码:
void test_zrangebyscore(sw::redis::Redis& redis) {
redis.flushall();
redis.zadd("zset", {
{"a", 10},
{"b", 20},
{"c", 30},
{"d", 40},
{"e", 50}
});
// 获取分数在20到40之间的元素
std::vector<std::pair<std::string, double>> result;
redis.zrangebyscore("zset", 20, 40, std::back_inserter(result));
// 输出: b:20 c:30 d:40
for (const auto& p : result) {
std::cout << p.first << ":" << p.second << " ";
}
}
chrono时间字面量说明
std::chrono_literals
std::chrono_literals
是 C++14 引入的命名空间,提供时间单位字面量,简化时间间隔的表示:
s
:秒(对应std::chrono::seconds
)ms
:毫秒(对应std::chrono::milliseconds
)us
:微秒(对应std::chrono::microseconds
)ns
:纳秒(对应std::chrono::nanoseconds
)min
:分钟(对应std::chrono::minutes
)h
:小时(对应std::chrono::hours
)
使用方法:
通过 using namespace std::chrono_literals;
引入命名空间后,可直接在数值后添加后缀表示时间:
// 10s 表示10秒,作为blpop的超时时间参数
auto result = redis.blpop({"key", "key2", "key3"}, 10s);
注意事项:
- 需包含头文件
<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::copy
int 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_iterator
int 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前面插入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()
:获取迭代器的下一个/上一个位置
迭代器类型的兼容性
需要注意的是,这些迭代器类型是有层次结构的:
- 随机访问迭代器 也是 双向迭代器
- 双向迭代器 也是 前向迭代器
- 前向迭代器 也是 输入迭代器和输出迭代器
这意味着,接受输入迭代器的算法也可以使用任何更高级的迭代器,而接受随机访问迭代器的算法则不能使用低级别的迭代器。