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

相关推荐
夜泉_ly34 分钟前
MySQL -安装与初识
数据库·mysql
power-辰南2 小时前
高并发系统架构设计全链路指南
分布式·系统架构·高并发·springcloud
qq_529835352 小时前
对计算机中缓存的理解和使用Redis作为缓存
数据库·redis·缓存
月光水岸New4 小时前
Ubuntu 中建的mysql数据库使用Navicat for MySQL连接不上
数据库·mysql·ubuntu
狄加山6754 小时前
数据库基础1
数据库
我爱松子鱼4 小时前
mysql之规则优化器RBO
数据库·mysql
闲猫4 小时前
go orm GORM
开发语言·后端·golang
丁卯4044 小时前
Go语言中使用viper绑定结构体和yaml文件信息时,标签的使用
服务器·后端·golang
chengooooooo4 小时前
苍穹外卖day8 地址上传 用户下单 订单支付
java·服务器·数据库
Rverdoser5 小时前
【SQL】多表查询案例
数据库·sql