[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返回结果集到各种不同容器的转换过程,无需为每种容器类型编写单独的处理逻辑

相关推荐
Asthenia041241 分钟前
Spring AOP 和 Aware:在Bean实例化后-调用BeanPostProcessor开始工作!在初始化方法执行之前!
后端
Asthenia04122 小时前
什么是消除直接左递归 - 编译原理解析
后端
Asthenia04122 小时前
什么是自上而下分析 - 编译原理剖析
后端
Asthenia04122 小时前
什么是语法分析 - 编译原理基础
后端
Asthenia04122 小时前
理解词法分析与LEX:编译器的守门人
后端
uhakadotcom2 小时前
视频直播与视频点播:基础知识与应用场景
后端·面试·架构
Asthenia04123 小时前
Spring扩展点与工具类获取容器Bean-基于ApplicationContextAware实现非IOC容器中调用IOC的Bean
后端
bobz9653 小时前
ovs patch port 对比 veth pair
后端
Asthenia04124 小时前
Java受检异常与非受检异常分析
后端