[Redis#11] cpp-redis | 通用命令 | optional | 插入迭代器

目录

接口特点

通用接口

示例代码

C++字符串类型

std::optional的使用

keys命令的使用

插入迭代器

标准库提供的插入迭代器接口


上篇文章我们讲完了 cpp-redis 的 基本设置 问题[Redis#10] scan | db_0 | redis_cli | RESP | C++-redis启动教程,这篇文章 我们将对于通用命令 进行进一步的讲解~

我们提到了redis-plus-plus ,它是一个基于 hiredis 实现的C++库,用于操作Redis数据库。具有与Redis原生命令几乎完全一致的接口风格,并且易于使用。本文将详细介绍如何使用这个库来执行常见的Redis操作。

接口特点

  • 参数传递:当函数需要接受多个值时,支持通过初始化列表或迭代器对进行传递。
  • 返回多数据:对于需要表示多个数据的情况,通常可以通过插入迭代器将结果添加到容器中。
  • 无效值处理 :在涉及无效值的情况下,通常会使用 std::optional 来表示。

通用接口

参考文档github--redis-plus-plus/src/sw/redis++ /redis.cpp

redis-plus-plus 支持多种Redis通用命令,包括:

  • get/set:获取/设置键值对。
  • exists:检查键是否存在。
  • del:删除键。
  • keys:搜索符合条件的键。
  • expire/ttl:设置/查询键的过期时间
  • type:获取键对应的值类型。

示例代码

#include <iostream>
#include <sw/redis++/redis++.h>

int main() {
    // 创建Redis对象,并指定服务器地址和端口
    sw::redis::Redis redis("tcp://127.0.0.1:6379");

    // 设置键值对
    redis.set("key1", "value1");
    std::string value = redis.get("key1").value_or("default_value");
    std::cout << "Value of key1: " << value << std::endl;

    // 检查键是否存在
    bool exists = (redis.exists("key1") == 1);
    std::cout << "Key1 exists: " << (exists ? "Yes" : "No") << std::endl;

    // 删除键
    redis.del("key1");

    // 搜索符合条件的键
    std::vector<std::string> keys;
    auto it = std::back_inserter(keys);
    redis.keys("*", it);
    for (const auto& key : keys) {
        std::cout << "Found key: " << key << std::endl;
    }

    // 设置键的过期时间
    redis.set("key2", "value2");
    redis.expire("key2", 10); // 10秒后过期
    long long ttl = redis.ttl("key2");
    std::cout << "TTL of key2: " << ttl << " seconds" << std::endl;

    // 获取键的类型
    std::string type = redis.type("key2");
    std::cout << "Type of key2: " << type << std::endl;

    return 0;
}

运行

C++字符串类型

  • std::string:可修改的字符串,既能读也能写。
  • std::string_view :只读的字符串视图,不能修改,针对只读操作效率更高。在C++17中引入。

示例

#include <iostream>
#include <string>
#include <string_view>

int main() {
    std::string str = "Hello, World!";
    std::string_view view(str);

    // 只读操作
    std::cout << "String View: " << view << std::endl;

    // 尝试修改会引发编译错误
    // view[0] = 'h'; // 错误:std::string_view是只读的

    return 0;
}

运行

std::optional的使用

  • std::optional:可以表示"非法值"或"无效值",例如在Redis中查询不到键时返回nil
  • 在C++14中通过boost库引入了optional类型,在C++17中被纳入标准库。

示例

#include <iostream>
#include <optional>
#include <string>

int main() {
    std::optional<std::string> value1 = "Hello";
    std::optional<std::string> value2; // 未初始化
    std::optional<std::string> value3 = "World";
    std::optional<std::string> value4; // 未初始化

    if (value1) {
        std::cout << *value1 << std::endl; // 输出: Hello
    }

    if (value3) {
        std::cout << *value3 << std::endl; // 输出: World
    }

    // 处理未初始化的情况
    if (!value2) {
        std::cout << "Value2 is not set" << std::endl;
    }

    if (!value4) {
        std::cout << "Value4 is not set" << std::endl;
    }

    return 0;
}

运行

keys命令的使用

keys函数用于 搜索所有符合条件的键,其声明如下:

template <typename Output>
void keys(const StringView &pattern, Output output);
  • 第一个参数pattern是匹配模式。
  • 第二个参数output是一个插入迭代器,用于获取符合条件的键,元素类型可以是std::stringStringView

示例代码

int main() {
    sw::redis::Redis redis("tcp://127.0.0.1:6379");
    redis.flushall();  // 清空数据库

    // 设置一些键值对
    redis.set("key1", "111");
    redis.set("key2", "222");
    redis.set("key3", "222");
    redis.set("key4", "222");

    // 准备存储结果的容器
    std::vector<std::string> result;
    auto it = std::back_inserter(result);  // 创建一个尾部插入迭代器

    // 执行keys命令
    redis.keys("*", it);

    // 输出结果
    for (auto& ret : result) {
        std::cout << ret << std::endl;
    }

    return 0;
}

输出结果

插入迭代器

插入迭代器是一种专门用于将元素插入到容器中的迭代器。主要种类包括:

  • std::front_insert_iterator:在容器头部插入。
  • std::back_insert_iterator:在容器尾部插入。
  • std::insert_iterator:在容器的任意位置插入。

这类迭代器的特性在于++--操作无效,核心操作是operator=

自定义插入迭代器示例

下面展示了一个简单的自定义插入迭代器的实现,用于向std::vector中插入元素:

template <typename T>
class InsertIterator {
public:
    // 构造函数,保存容器引用和插入位置的迭代器
    InsertIterator(std::vector<T>& vec, typename std::vector<T>::iterator pos)
        : vec_(vec), pos_(pos) {}

    // 重载赋值操作符,实现插入逻辑
    InsertIterator& operator=(const T& value) {
        pos_ = vec_.insert(pos_, value);
        return *this;
    }

    // 重载前置和后置增加操作符,因为插入操作不改变迭代器位置
    InsertIterator& operator++() { return *this; }
    InsertIterator& operator++(int) { return *this; }

    // 重载解引用操作符,以便可以链式调用
    InsertIterator& operator*() { return *this; }

private:
    std::vector<T>& vec_;
    typename std::vector<T>::iterator pos_;
};
标准库提供的插入迭代器接口

要获取对应容器的插入迭代器,可以使用标准库提供的接口:

  • std::front_inserter(container);
  • std::back_inserter(container);
  • std::inserter(container, position);

对于像std::vector这样的容器,由于提供了头尾删除接口,可以方便地使用front_inserterback_inserter。对于如std::set这样不支持随机访问的容器,则通常只能使用inserter

优点:可以简化从Redis返回结果集到各种不同容器的转换过程,无需为每种容器类型编写单独的处理逻辑

相关推荐
麦香--老农12 分钟前
windows 钉钉缓存路径不能修改 默认C盘解决方案
缓存·钉钉
m0_7482448320 分钟前
StarRocks 排查单副本表
大数据·数据库·python
C++忠实粉丝31 分钟前
Redis 介绍和安装
数据库·redis·缓存
李洋-蛟龙腾飞公司31 分钟前
HarmonyOS Next 应用元服务开发-分布式数据对象迁移数据文件资产迁移
分布式·华为·harmonyos
wmd131643067121 小时前
将微信配置信息存到数据库并进行调用
数据库·微信
丰云1 小时前
一个简单封装的的nodejs缓存对象
缓存·node.js
Oneforlove_twoforjob1 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
泰伦闲鱼1 小时前
nestjs:GET REQUEST 缓存问题
服务器·前端·缓存·node.js·nestjs
是阿建吖!1 小时前
【Linux】基础IO(磁盘文件)
linux·服务器·数据库
搬码后生仔1 小时前
asp.net core webapi项目中 在生产环境中 进不去swagger
chrome·后端·asp.net