
目錄
- `通用 API`
- `連接 Redis`
- `1. get/set`
- `2. exists 方法`
- `3. del 方法`
- `4. keys 方法`
- `5. expire 方法`
- `6. ttl 方法`
- `7. type 方法`
- `8. flushall 方法`
- `String 類型 API`
- `1. get/set 方法`
- `2. mset 函數`
- `3. mget 方法`
- `4. append 方法`
- `5. strlen 方法`
- `List 類型 API`
- `1. lpush 方法`
- `2. rpush 方法`
- `3. lpop 方法`
- `4. rpop 方法`
- `5. blpop 方法`
- `6. brpop 方法`
- `7. lrange 方法`
- `8. llen 方法`
- `Hash 類型 API`
- `1. hset 與 hget 方法`
- `2. hmset 與 hmget 方法`
- `3. hkeys 與 hvals 方法`
- `4. hgetall 方法`
- `5. hexists 方法`
- `6. hdel 方法`
- `7. hlen 方法`
- `Set 類型 API`
- `1. sadd 和 smembers 方法`
- `2. srem 方法`
- `3. sismember 方法`
- `4. scard 方法`
- `5. sinter 與 sinterstore 方法`
- `6. sunion 與 sunionstore 方法`
- `7. sdiff 與 sdiffstore 方法`
- `ZSet 類型 API`
- `1. zadd 和 zrange 方法`
- `2. zscore 方法`
- `3. zrank 方法`
- `4. zcard 方法`
- `5. zrem 方法`
- `6. zrangebyscore 方法`
- `chrono時間字面量說明`
- `C++中迭代器類型`
- `1. 輸入迭代器(Input Iterator)`
- `2. 輸出迭代器(Output Iterator)`
- `std::copy函數`
- `3. 前向迭代器(Forward Iterator)`
- `4. 雙向迭代器(Bidirectional Iterator)`
- `5. 隨機訪問迭代器(Random Access Iterator)`
- `迭代器類型的兼容性`
通用 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") });// 第二種寫法: 將多個鍵值對組織到容器中,通過迭代器傳遞給msetstd::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; // 輸出: 11auto 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; // 輸出: 5len = 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, cfor (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, cfor (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, bfor (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 eres.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; // 輸出: 3std::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; // 輸出: trueexists = 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; // 輸出: 2std::vector<std::string> fields;redis.hkeys("user", std::back_inserter(fields));// 輸出: namefor (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; // 輸出: 2std::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; // 輸出: 2std::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; // 輸出: trueis_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; // 輸出: 3std::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; // 輸出: 5std::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; // 輸出: 1std::vector<std::string> members;redis.zrange("zset", 0, -1, std::back_inserter(members));// 輸出: a cfor (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:40for (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::copyint 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_iteratorint 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前面插入10std::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()
:獲取迭代器的下一個/上一個位置
迭代器類型的兼容性
需要注意的是,這些迭代器類型是有層次結構的:
- 隨機訪問迭代器 也是 雙向迭代器
- 雙向迭代器 也是 前向迭代器
- 前向迭代器 也是 輸入迭代器和輸出迭代器
這意味著,接受輸入迭代器的算法也可以使用任何更高級的迭代器,而接受隨機訪問迭代器的算法則不能使用低級別的迭代器。