文章目录
- 本篇摘要
- 一.如何安装C++的Redis客户端
- 二.进行连接Redis服务端测试
- 三.C++客户端使用通用命令
-
- 基于set与get简单测试
-
- 其他要点事项
-
- [1. Redis 字符串交互的类型选择](#1. Redis 字符串交互的类型选择)
- [2. `std::optional` 的作用与使用](#2.
std::optional的作用与使用) - [3. 实际代码中的问题与处理](#3. 实际代码中的问题与处理)
- 基于exists简单测试
- 基于del简单测试
- 基于keys匹配操作简单测试
-
- [1. 迭代器是啥以及分类?](#1. 迭代器是啥以及分类?)
- [2. 插入迭代器:专门用来"插元素"的迭代器](#2. 插入迭代器:专门用来“插元素”的迭代器)
- [3. 插入迭代器咋用?](#3. 插入迭代器咋用?)
- [4. 为啥要搞插入迭代器?------解耦合!](#4. 为啥要搞插入迭代器?——解耦合!)
- 基于expire与ttl简单测试
- 测试总代码
- 四.本篇小结

本篇摘要
本文详细介绍了 C++ 操作 Redis 的完整流程:从安装 Redis 客户端库(hiredis 和 redis-plus-plus)到编译链接,再到通过代码测试 Redis 基础命令(如 set/get、exists、del、keys、expire/ttl),并讲解了迭代器、std::optional 等 C++ 特性在其中的应用,最后提供了完整测试代码,帮助开发者快速上手 Redis C++ 客户端开发。
一.如何安装C++的Redis客户端
在上篇文章,已经可以访问到对应的github了,然后只需要下载现成的,安装即可:
进行搜索找到对应仓库:

首先进行c版本对应的安装:


bash
apt install libhiredis-dev
然后找到我们对应新建立一个目录进行clone即可:
bash
git clone https://github.com/sewenew/redis-plus-plus.git


下面创建个目录进行cmake解析:
安装cmake:
bash
apt install cmake

下面进行camke(前提是必须能找到对应的 CMakeLists.txt 文件)

最后直接make等待即可:

- 然后能发现对应目录很多之后需要链接的一些库等文件,这里可以把它移动到系统默认搜索的路径,减少麻烦:
使用:
bash
make install

二.进行连接Redis服务端测试
首先利用VScode进行编写:
这里我们需要包含对应的对应API的文件:redis.h
下面几个规则:
#include <>:在系统目录中搜索头文件。#include "":在项目目录中搜索头文件。
因此需要找到对应路径,这里可以搜索:

因为系统目录头文件就是include里,因此可以这样包含:
cpp
#include<sw/redis++/redis.h>
下面检查下是否对应端口启动了对应redis监听:

下面编写代码:
cpp
#include<iostream>
#include<string>
#include<sw/redis++/redis.h>
using std::string;
using std::iostream;
using std::cout;
using std::cin;
using namespace sw::redis;
int main(){
auto redis= Redis("tcp://127.0.0.1:6379");
auto x=redis.ping();
cout<<x<<std::endl;
}
关于相关api使用可以见对应官网示例(官网示例):


下面进行Makefile书写:
需要进行链接的库:
1.libhiredis.a
2.libredis++.a
3.pthread
前两个我们已经移动到系统的路径下了,因此只需表明具体文件位置即可(如果是不在系统路径需要 -L 指明路径等):
下面我们用find查下位置:

find介绍:
find 是 Linux/Unix 系统中一个强大的 文件搜索工具,用于在 指定目录及其子目录 下递归查找符合特定条件的文件或目录。
基本语法:
bash
find [查找路径] [查找条件] [处理动作]
如:
bash
find /usr/ -name 'libhiredis*'
-
查找路径:指定从哪个目录开始搜索(默认当前目录 .)。
-
查找条件:定义搜索规则(如文件名、类型、大小、时间等)。
-
处理动作:对找到的文件执行的操作(如打印、删除等,默认是 -print显示文件名)。
对应Makefile:
cpp
halo: halo.cc
g++ halo.cc -std=c++17 -o halo /usr/local/lib/libredis++.a /usr/lib/x86_64-linux-gnu/libhiredis.a -pthread
.PHONY:clean
clean:
rm halo
注:因为这里链接前两个库的顺序不嫩颠倒,因为最后一个库包含前一个库的使用。
执行成功:

三.C++客户端使用通用命令
基于set与get简单测试
下面编写代码进行测试:
对应代码:
cpp
#include <iostream>
#include <string>
#include <sw/redis++/redis.h>
using std::cin;
using std::cout;
using std::endl;
using std::iostream;
using std::string;
using namespace sw::redis;
int main()
{
auto redis = Redis("tcp://127.0.0.1:6379");
redis.flushall();
auto ok1 = redis.set("key1", "111");
auto val1 = redis.get("key1");
if(val1.has_value()) cout << val1.value() << endl;
auto ok2 = redis.set("key2", "222");
auto val2 = redis.get("key2");
if(val2.has_value()) cout << val2.value() << endl;
auto val = redis.get("key3");
if(val.has_value()) cout << val.value() << endl;
}
测试效果:

注:对应set使用的时候就当输入key+value使用,而对应get得到返回是一个对象,先要判断里面有没有值,然后再操作。
其他要点事项
1. Redis 字符串交互的类型选择
std::string:可修改(既能读也能写)。std::string_view(C++17 引入):只读 视图,针对 "只读操作" 做了很多优化,效率比std::string更高。- 项目中也常自己封装类似
sw::redis::OptionalString这样的类型,用来更灵活地处理 "可能为空" 的场景。
2. std::optional 的作用与使用
std::optional 用来表示 "可能有值,也可能没有(无效值 / nil)" 的语义:
- 直接用
std::string难以直观表达 "空值"(nullptr本身不是string类型),而optional可以显式表示 "有值" 或 "无值"。 - 不需要为
optional重载<<运算符,只需取出内部元素再输出即可(它更像一个 "单元素容器")。
3. 实际代码中的问题与处理
- 访问
optional内部元素时,若optional处于 "无效状态(无值)",会触发std::bad_optional_access异常(类似图中 "SIGABRT" 这类程序崩溃)。

- 处理思路:
- 显式
catch异常; - 在访问前先判断
optional是否有值(has_value()),避免非法访问。
- 显式
基于exists简单测试
测试代码:
cpp
void test_exist(Redis &redis)
{
redis.flushall();
auto ok1 = redis.set("key1", "111");
auto ok2 = redis.set("key2", "222");
auto ex1 = redis.exists("key3");
cout << "key3 exist: " << ex1 << endl;
auto ex2 = redis.exists({"key1", "key2", "key3"});
cout << "key1 key2 key3 exist: " << ex2 << endl;
}
测试结果:


- 返回对应存在的个数,对应的
initializer,因此支持花括号。
有个疑问,对应的flushall是放在代码结尾还是开头?
答: 单元测试里 Redis 清理数据,放开始更好。
- 放结束若中途报错,清理代码可能没执行,下次测试会受残留数据影响;
- 放开始能保证每次测试环境"干净",还方便中途检查数据。
基于del简单测试
测试代码:
cpp
void test_del(Redis &redis)
{
redis.flushall();
auto ok1 = redis.set("key1", "111");
auto ok2 = redis.set("key2", "222");
long long d1 = redis.del("key1");
long long d2 = redis.del("key2");
auto ex1 = redis.exists("key3");
cout << "key3 exist: " << ex1 << endl;
auto ex2 = redis.exists({"key1", "key2", "key3"});
cout << "key1 key2 key3 exist: " << ex2 << endl;
}
测试效果:

基于keys匹配操作简单测试
测试代码:
cpp
void test_keys(Redis &redis)
{
redis.flushall();
auto ok2 = redis.set("key2", "111");
auto ok3 = redis.set("key3", "111");
auto ok4 = redis.set("key4", "111");
auto ok5 = redis.set("key5", "111");
vector<string> v;
auto bit=std::back_inserter(v);
redis.keys("key*",bit);
print(v);
v.clear();
redis.keys("*5",bit);
print(v);
}
测试效果:

这里用到了对应的迭代器,需要我们手动传递进去,然后对应内部会填充好对应容器。
1. 迭代器是啥以及分类?
可以把迭代器理解成"指针加强版",用来遍历容器(比如数组、链表、vector这些)。不同迭代器"能力"不一样,能干的活也不一样:
- 最弱的只能读/写一个元素(输入/输出迭代器);
- 强点的能往前跳着读(前向迭代器);
- 再强的能前后跳(双向迭代器);
- 最强的能直接跳到任意位置(随机访问迭代器,比如vector就支持)。
不同的迭代器决定了你能用哪些STL算法(比如sort就要求"随机访问迭代器",因为得随便跳位置排序)。
2. 插入迭代器:专门用来"插元素"的迭代器
普通迭代器只是"指位置",插入迭代器 = 位置 + "往哪插"的动作。STL给了3种插入方式:
front_insert_iterator:往容器最开头 插(容器得支持push_front,比如list、deque);back_insert_iterator:往容器最后面 插(容器得支持push_back,比如vector、list、deque);insert_iterator:往容器任意位置前插(得指定插哪)。
3. 插入迭代器咋用?
不用自己手动写,C++给了3个辅助函数,直接调用就行:
front_inserter(容器)→ 生成"往开头插"的迭代器;back_inserter(容器)→ 生成"往末尾插"的迭代器;inserter(容器, 位置)→ 生成"往指定位置前插"的迭代器。
插入迭代器的关键是=操作:给它赋值=,就会把值插到对应位置 。比如用back_inserter时,it = 值 就相当于容器.push_back(值)。
4. 为啥要搞插入迭代器?------解耦合!
直接操作容器(比如push_back)不够灵活。插入迭代器让"算法(比如排序、拷贝)"和"容器(比如vector、list)"分开------算法只管用迭代器操作,不用关心容器具体咋插元素。这样同一个算法能适配不同容器,代码更通用。
一句话概括:插入迭代器是STL里专门帮我们往容器里"插元素"的工具,用辅助函数创建,赋值就插,还能让算法和容器解耦,写代码更省心。
基于expire与ttl简单测试
测试代码:
cpp
void test_expire_ttl(Redis &redis)
{
redis.flushall();
auto ok5 = redis.set("key5", "111");
// redis.expire("key5",std::chrono::seconds(10));
using namespace std::chrono_literals;
redis.expire("key5", 10s);
// 进行对进程休眠,方面服务端计时:
std::this_thread::sleep_for(3s);
auto t = redis.ttl("key5");
cout << t << endl;
}
测试效果:

这里对于传递时间两种格式:
第一种:
cpp
#include<chrono>
redis.expire("key5",std::chrono::seconds(10));
第二种:
cpp
#include<chrono>
using namespace std::chrono_literals;
redis.expire("key5", 10s);
注:
-
Linux 与 Windows 的系统休眠函数不同 :在 Linux 下常用
sleep(s)实现以秒为单位的休眠;在 Windows 下则是Sleep(ms)(注意 Windows 下Sleep首字母大写,且参数单位是毫秒)。这体现了"系统函数与系统强相关,相同功能在不同系统可能对应完全不同的函数实现"这一特点。 -
使用标准库
<thread>中的sleep_for:相比于依赖特定系统的函数,C++ 标准库提供的thread类里的sleep_for是更优选择。使用时需要先包含头文件#include <thread>,示例代码为sleep_for(3s),这里3s是 C++ 里支持的字面值常量(如算法常见的500000l,1.1f等等),表示延迟 3 秒;如果想要延迟 3 毫秒,也可以写成3ms这种字面值形式。
测试总代码
cpp
#include <iostream>
#include <string>
#include <vector>
#include <sw/redis++/redis.h>
#include <chrono>
#include <thread>
using std::cin;
using std::cout;
using std::endl;
using std::iostream;
using std::string;
using std::vector;
using namespace sw::redis;
template <class T>
void print(T &arr)
{
for (auto it : arr)
{
cout << it << endl;
}
}
void test_get_set(Redis &redis)
{
redis.flushall();
auto ok1 = redis.set("key1", "111");
auto val1 = redis.get("key1");
if (val1.has_value())
cout << val1.value() << endl;
auto ok2 = redis.set("key2", "222");
auto val2 = redis.get("key2");
if (val2.has_value())
cout << val2.value() << endl;
auto val = redis.get("key3");
if (val.has_value())
cout << val.value() << endl;
}
void test_exist(Redis &redis)
{
redis.flushall();
auto ok1 = redis.set("key1", "111");
auto ok2 = redis.set("key2", "222");
auto ex1 = redis.exists("key3");
cout << "key3 exist: " << ex1 << endl;
auto ex2 = redis.exists({"key1", "key2", "key3"});
cout << "key1 key2 key3 exist: " << ex2 << endl;
}
void test_del(Redis &redis)
{
redis.flushall();
auto ok1 = redis.set("key1", "111");
auto ok2 = redis.set("key2", "222");
long long d1 = redis.del("key1");
long long d2 = redis.del("key2");
auto ex1 = redis.exists("key3");
cout << "key3 exist: " << ex1 << endl;
auto ex2 = redis.exists({"key1", "key2", "key3"});
cout << "key1 key2 key3 exist: " << ex2 << endl;
}
void test_keys(Redis &redis)
{
redis.flushall();
auto ok2 = redis.set("key2", "111");
auto ok3 = redis.set("key3", "111");
auto ok4 = redis.set("key4", "111");
auto ok5 = redis.set("key5", "111");
vector<string> v;
auto bit = std::back_inserter(v);
redis.keys("key*", bit);
print(v);
v.clear();
redis.keys("*5", bit);
print(v);
}
void test_expire_ttl(Redis &redis)
{
redis.flushall();
auto ok5 = redis.set("key5", "111");
// redis.expire("key5",std::chrono::seconds(10));
using namespace std::chrono_literals;
redis.expire("key5", 10s);
// 进行对进程休眠,方面服务端计时:
std::this_thread::sleep_for(3s);
auto t = redis.ttl("key5");
cout << t << endl;
}
int main()
{
Redis redis("tcp://127.0.0.1:6379");
redis.command("select", 6);
// test_get_set(redis);
// test_exist(redis);
// test_del(redis);
// test_keys(redis);
test_expire_ttl(redis);
}
四.本篇小结
本文用 C++ 连接 Redis:先安装客户端库(hiredis + redis-plus-plus),再通过代码测试 set/get、exists、del、keys、expire/ttl 等命令,结合 std::optional、迭代器等 C++ 特性解析常见问题,最后给出完整可运行代码,助你轻松掌握 Redis C++ 开发!