C/C++---rdbuf()函數

在C++中,rdbuf() 是I/O流庫中的一個核心成員函數,主要用于訪問和操作流對象的緩沖區。這個函數在底層數據處理、流重定向以及自定義流操作等場景中應用廣泛。下面將從多個方面詳細解析 rdbuf() 函數。

基本概念與函數原型

rdbuf()std::basic_ios 類的成員函數,其主要功能是獲取或設置流對象關聯的緩沖區。不同的流類(如 std::ifstreamstd::ofstreamstd::stringstream 等)都繼承了這個函數。

該函數有兩種重載形式:

  1. 獲取緩沖區指針

    std::basic_streambuf<charT, traits>* rdbuf() const;
    

    這個重載形式會返回一個指向當前流緩沖區的指針,可用于讀取或修改緩沖區狀態。

  2. 設置緩沖區指針

    std::basic_streambuf<charT, traits>* rdbuf(std::basic_streambuf<charT, traits>* sb
    );
    

    此重載形式會將流對象關聯到新的緩沖區 sb,并返回原來的緩沖區指針。

流緩沖區的工作原理

在深入了解 rdbuf() 之前,有必要先了解流緩沖區的基本工作原理:

  • 流與緩沖區的關系:在C++的I/O系統中,流(如 std::coutstd::ifstream)負責提供操作接口,而緩沖區(std::streambuf)則負責實際的數據傳輸和存儲。
  • 緩沖區類型:根據流的方向,緩沖區可分為輸入緩沖區(std::streambuf)和輸出緩沖區(std::streambuf)。例如,std::ifstream 使用輸入緩沖區,std::ofstream 使用輸出緩沖區。
  • 緩沖區操作:緩沖區提供了一系列底層操作函數,像 sgetc()(獲取字符)、sputc()(放置字符)、pubsync()(同步緩沖區)等。

rdbuf() 的常見用法

1. 直接操作流緩沖區

借助 rdbuf() 函數獲取緩沖區指針后,就能直接調用緩沖區的底層操作函數。這種方式在需要高效處理大量數據時非常有用。

下面是一個示例,展示了如何通過 rdbuf() 直接讀取文件內容:

#include <iostream>
#include <fstream>
#include <streambuf>int main() {std::ifstream file("example.txt");if (!file) {std::cerr << "無法打開文件" << std::endl;return 1;}// 獲取文件流的緩沖區指針std::streambuf* buf = file.rdbuf();// 使用緩沖區直接讀取數據char c;while ((c = buf->sbumpc()) != EOF) {std::cout << c;}file.close();return 0;
}
2. 流重定向

rdbuf() 的一個重要應用是實現流重定向,即將一個流的輸入或輸出關聯到另一個緩沖區。這在捕獲輸出、日志記錄等場景中經常會用到。

以下是一個流重定向的示例:

#include <iostream>
#include <fstream>
#include <streambuf>
#include <string>int main() {std::ofstream file("output.txt");if (!file) {std::cerr << "無法打開文件" << std::endl;return 1;}// 保存原始的cout緩沖區std::streambuf* original_cout_buf = std::cout.rdbuf();// 將cout重定向到文件std::cout.rdbuf(file.rdbuf());// 輸出到文件std::cout << "這段文字會被寫入文件" << std::endl;// 恢復cout的原始緩沖區std::cout.rdbuf(original_cout_buf);// 輸出到控制臺std::cout << "這段文字會顯示在控制臺" << std::endl;file.close();return 0;
}
3. 內存與字符串流操作

在使用 std::stringstream 時,rdbuf() 可用于直接訪問底層的字符串緩沖區,從而高效地操作內存中的數據。

下面是一個相關示例:

#include <iostream>
#include <sstream>
#include <streambuf>int main() {std::stringstream ss("Hello, World!");// 獲取字符串流的緩沖區std::streambuf* buf = ss.rdbuf();// 讀取緩沖區內容std::string content;char c;while ((c = buf->sbumpc()) != EOF) {content += c;}std::cout << "讀取的內容: " << content << std::endl;// 重置緩沖區位置buf->pubseekpos(0);// 再次讀取std::string content2;while ((c = buf->sbumpc()) != EOF) {content2 += c;}std::cout << "再次讀取的內容: " << content2 << std::endl;return 0;
}
4. 自定義流緩沖區

通過繼承 std::streambuf 類并實現相應的虛函數,能夠創建自定義的流緩沖區,然后使用 rdbuf() 將其關聯到流對象上。

下面是一個簡單的自定義緩沖區示例:

#include <iostream>
#include <streambuf>
#include <string>class SimpleBuffer : public std::streambuf {
public:SimpleBuffer(std::string& str) {char* begin = &str[0];char* end = begin + str.size();setg(begin, begin, end); // 設置輸入緩沖區}
};int main() {std::string data = "Hello from custom buffer!";SimpleBuffer buffer(data);std::istream in(&buffer);std::string line;std::getline(in, line);std::cout << "讀取的內容: " << line << std::endl;return 0;
}

高級應用場景

1. 二進制數據處理

在處理二進制數據時,rdbuf() 能提供比 >><< 更高效的操作方式,避免了格式化帶來的開銷。

以下是一個二進制數據處理的示例:

#include <iostream>
#include <fstream>
#include <streambuf>
#include <vector>int main() {std::ifstream file("data.bin", std::ios::binary);if (!file) {std::cerr << "無法打開文件" << std::endl;return 1;}// 獲取文件大小file.seekg(0, std::ios::end);std::streamsize size = file.tellg();file.seekg(0, std::ios::beg);// 讀取全部二進制數據std::vector<char> buffer(size);file.rdbuf()->sgetn(buffer.data(), size);// 處理數據std::cout << "讀取的字節數: " << buffer.size() << std::endl;file.close();return 0;
}
2. 流過濾器實現

利用 rdbuf() 可以實現流過濾器,在數據傳輸過程中對其進行處理,例如壓縮、加密等操作。

下面是一個簡單的流過濾器示例:

#include <iostream>
#include <streambuf>
#include <string>class UpperCaseFilter : public std::streambuf {
private:std::streambuf* src;char buffer[1];public:UpperCaseFilter(std::streambuf* s) : src(s) {setg(buffer, buffer, buffer); // 設置空的輸入緩沖區}protected:int underflow() override {int c = src->sbumpc();if (c != EOF) {buffer[0] = static_cast<char>(std::toupper(c));setg(buffer, buffer, buffer + 1);}return c;}
};int main() {std::string data = "hello, world!";std::istringstream iss(data);UpperCaseFilter filter(iss.rdbuf());std::istream in(&filter);std::string line;std::getline(in, line);std::cout << "轉換后的內容: " << line << std::endl; // 輸出: HELLO, WORLD!return 0;
}
3. 性能優化

在處理大量數據時,直接使用 rdbuf() 進行操作可以減少中間層的開銷,從而提高程序的性能。

下面是一個性能對比示例:

#include <iostream>
#include <fstream>
#include <streambuf>
#include <string>
#include <chrono>int main() {const int N = 1000000;// 使用流操作符auto start1 = std::chrono::high_resolution_clock::now();{std::ostringstream oss;for (int i = 0; i < N; ++i) {oss << i;}}auto end1 = std::chrono::high_resolution_clock::now();auto duration1 = std::chrono::duration_cast<std::chrono::milliseconds>(end1 - start1).count();// 使用rdbuf()直接操作auto start2 = std::chrono::high_resolution_clock::now();{std::ostringstream oss;std::streambuf* buf = oss.rdbuf();for (int i = 0; i < N; ++i) {std::string s = std::to_string(i);buf->sputn(s.data(), s.size());}}auto end2 = std::chrono::high_resolution_clock::now();auto duration2 = std::chrono::duration_cast<std::chrono::milliseconds>(end2 - start2).count();std::cout << "使用流操作符耗時: " << duration1 << " 毫秒" << std::endl;std::cout << "使用rdbuf()耗時: " << duration2 << " 毫秒" << std::endl;std::cout << "性能提升: " << (100.0 * (duration1 - duration2) / duration1) << "%" << std::endl;return 0;
}

注意事項與最佳實踐

在使用 rdbuf() 函數時,有以下幾點需要注意:

  • 生命周期管理:當使用 rdbuf(sb) 設置新的緩沖區時,流對象不會接管 sb 的所有權,因此需要確保 sb 在流對象使用期間一直有效。
  • 同步問題:在修改緩沖區后,可能需要調用 pubsync() 來確保數據的同步,特別是在混合使用高層流操作和底層緩沖區操作時。
  • 異常安全:在進行流重定向操作時,建議使用RAII技術管理緩沖區的恢復,以確保異常發生時流狀態能正確恢復。
  • 類型匹配rdbuf() 返回的指針類型要與流的字符類型相匹配,例如 std::wifstreamrdbuf() 返回 std::wstreambuf*

總結

rdbuf() 函數是C++ I/O流庫中的一個強大工具,它提供了直接訪問和操作流緩沖區的能力。通過 rdbuf(),我們可以實現流重定向、自定義流操作、高效的數據處理等功能。在性能敏感的場景或需要底層控制的情況下,合理使用 rdbuf() 能夠顯著提升程序的效率和靈活性。不過,由于該函數涉及底層操作,使用時需要特別注意內存管理和同步問題。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/89167.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/89167.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/89167.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【LLM】從零到一構建一個小型LLM--MiniGPT

從零到一構建一個小型LLM (Small Language Model)暫時起名為MiniGPT。這個模型將專注于因果語言建模 (Causal Language Modeling)&#xff0c;這是許多現代LLM&#xff08;如GPT系列&#xff09;的核心預訓練任務。模型設計&#xff1a; 我們設計的模型是一個僅包含解碼器 (Dec…

網絡安全威脅下的企業困境與破局技術實踐

前言&#xff1a;網絡安全威脅下的企業困境 在數字化轉型的浪潮中&#xff0c;企業對信息技術的依賴程度日益加深&#xff0c;但隨之而來的網絡安全威脅也愈發嚴峻。據統計&#xff0c;全球每年因網絡安全事件造成的經濟損失高達數萬億美元&#xff0c;其中中小企業更是成為了網…

[RAG system] 信息檢索器 | BM25 Vector | Pickle格式 | HybridRetriever重排序

第六章&#xff1a;信息檢索器 在上一章中&#xff0c;我們成功完成了知識庫攝入流程。這是巨大的進步~ 我們精心準備了文檔"塊"&#xff08;類似獨立的索引卡&#xff09;&#xff0c;并將其存儲在兩套智能歸檔系統中&#xff1a;向量數據庫&#xff08;用于基于含…

Android 高通平臺修改音頻參數效果文件-優化音頻效果

Android 高通平臺如何音頻效果 修改音頻參數效果文件-優化音頻效果 按如下方式修改。 開發云 - 一站式云服務平臺 diff --git a/vendor/qcom/proprietary/mm-audio/audcal/family-b/acdbdata//MTP/workspaceFile.qwsp b/vendor/qcom/proprietary/mm-audio/audcal/family-b/acdb…

Install Docker Engine on UbuntuMySQL

Install Docker Engine on Ubuntu&&MySQL安裝docker安裝mysql客戶端連接數據庫我真氣鼠了&#xff0c;今天得到一個血淚的教訓&#xff0c;以后一定看官方文檔&#xff01;&#xff01;&#xff01;學的課用的centos&#xff0c;指令全是yum&#xff0c;我這邊不通用&a…

智能人體感應模塊HC-SR501應用指南---使用esp32

人體熱釋電探頭紅外感應模塊 人體感應開關HC-SR501藍板新款 綠板-淘寶網 HC-SR501 人體紅外感應電子模塊傳感器熱釋電探頭感應開關RD-624-tmall.com天貓 模塊信息 HC-SR501人體感應開關是一種基于紅外線技術的自動控制模塊&#xff0c;廣泛應用于安防、智能家居和自動控制等領…

加速度傳感器方向校準方法

保持平板平放在桌面上&#xff0c;將后置攝像頭保持在平板的左上后方&#xff0c;或者右上后方&#xff0c;此為機器的正方向 1、以一臺重力方向正常的機器做測試&#xff0c;通過DeviceInfoHw這個軟件的加速度測試功能【Accelerometer Test】我們可以知道 X方向數據測試&#…

【OpenHarmonyOS應用開發】

OpenHarmonyOS應用開發1.OpenHarmonyOS應用開發環境安裝2.初始化項目3.連接潤和軟件的開發板套件1.OpenHarmonyOS應用開發環境安裝 進入HarmonyOS下載鴻蒙應用開發工具DevEco Studio 5.0.7.200版本。 雙擊打開下載好的可執行文件&#xff0c;點擊下一步。 如果已經安裝過&am…

50天50個小項目 (Vue3 + Tailwindcss V4) ? | AutoTextEffect(自動打字機)

&#x1f4c5; 我們繼續 50 個小項目挑戰&#xff01;—— AutoTextEffect組件 倉庫地址&#xff1a;https://github.com/SunACong/50-vue-projects 項目預覽地址&#xff1a;https://50-vue-projects.vercel.app/。 利用 Vue 3 的 Composition API 和一些簡單的 CSS 動畫來構…

[RAG] LLM 交互層 | 適配器模式 | 文檔解析器(`docling`庫, CNN, OCR, OpenCV)

第二章&#xff1a;LLM 交互層 在上一章中&#xff0c;我們學習了作為"項目總控"的管道協調器&#xff0c;它負責協調 RAG 系統中各個功能模塊。 其中最重要的協調對象之一&#xff0c;便是負責與大型語言模型&#xff08;LLM&#xff09;進行智能交互的LLM 交互層…

Golang 并發快速上手

文章目錄1. 為什么要用協程&#xff1f;1.1 進程與線程1.2 協程1.3 線程和協程的區別線程協程1.4 Go 協程&#xff08;goroutines&#xff09;和協程&#xff08;coroutines&#xff09;2.Go 協程基本內容2.1 channel2.2 select2.3 future 模式3. 實踐示例3.1 并發處理多個網絡…

ESP32輕松實現UDP無線通信

ESP32支持UDP通信&#xff0c;這是一種輕量級、高效的通信協議&#xff0c;適用于需要快速數據傳輸但對數據可靠性要求不高的場景。以下是關于ESP32如何實現UDP通信的詳細說明&#xff1a; 1. UDP協議簡介及其適用場景 UDP&#xff08;用戶數據報協議&#xff09;是一種無連接的…

Electron實現“僅首次運行時創建SQLite數據庫”

在桌面應用中&#xff0c;SQLite因其輕量、嵌入式特性成為本地存儲的熱門選擇。但若重復初始化數據庫&#xff0c;會導致數據覆蓋或冗余。本文將詳解如何讓Electron應用僅在首次啟動時創建SQLite數據庫&#xff0c;后續啟動直接連接現有庫。一、核心邏輯與實現原理 核心思路&am…

阿里開源AI大模型ThinkSound如何為視頻配上靈魂之聲

目錄 前言 一、當AI解決視頻配音的困境 二、引入“思維鏈”&#xff1a;讓AI像專業音效師一樣思考 三、背后的技術支撐 四、未來ThinkSound會如何改變我們的世界&#xff1f; 總結 &#x1f3ac; 攻城獅7號&#xff1a;個人主頁 &#x1f525; 個人專欄:《AI前沿技術要聞…

圖論(1):多叉樹

多叉樹一、基礎知識1. 圖 & 樹2. 模板2.1 建圖二、簡單循環1. 【模板】樹的路徑求和2. 道路修建&#xff08;改&#xff09;3. 聯合權值4. 毛毛蟲樹三、自頂向下/自底向上1. 醫療中心2. 【模板】樹的直徑3. 【模板】最大子樹和4. 信號放大器一、基礎知識 1. 圖 & 樹 …

樓宇自動化:Modbus 在暖通空調(HVAC)中的節能控制(一)

引言**在當今的建筑領域&#xff0c;樓宇自動化正扮演著愈發關鍵的角色&#xff0c;它致力于提升建筑的舒適度、安全性以及能源效率。而暖通空調&#xff08;HVAC&#xff09;系統作為樓宇自動化中的核心部分&#xff0c;其能耗在整個建筑能耗中占比相當高&#xff0c;據相關數…

【SpringBoot】注冊條件+自動配置原理+自定義starter

注冊條件注入到容器內實體類型對象的屬性都是null&#xff0c;這些對象并沒有什么實際的意義&#xff0c;因為實體類的對象就是來封裝對象的&#xff0c;結果你這些對象中什么都沒有&#xff1b;解決方法是1.給這些屬性賦值然后再注入bean但是這些屬性又是固定的不是很好&#…

Server reports Content-Length Mismatch 的根源與解決方案

“服務器聲明604字節&#xff0c;Yum卻期待28680字節”——當包管理器與倉庫服務器之間的信任崩塌時&#xff0c;會發生什么&#xff1f;問題重現 yum install package_name ... Interrupted by header callback: Server reports Content-Length: 604 but expected size is: 28…

基于 Python/PHP/Node.js 的淘寶 API 商品數據抓取開發教程

在電商數據分析、競品監控等場景中&#xff0c;抓取淘寶商品數據是常見需求。淘寶開放平臺&#xff08;Open Platform&#xff09;提供了標準化的 API 接口&#xff0c;通過合法途徑調用可高效獲取商品信息。本文將分別基于 Python、PHP、Node.js 三種語言&#xff0c;詳解淘寶…

【Tensor的創建】——深度學習.Torch框架

目錄 1 Tensor概述 2 Tensor的創建 2.1 基本的創建方式 2.1.1 torch.tensor 2.1.2 torch.Tensor 2.2 創建線性和隨機張量 2.2.1 創建線性張量 2.2.2 隨機張量 1 Tensor概述 PyTorch會將數據封裝成張量&#xff08;Tensor&#xff09;進行計算&#xff0c;張量就是元素為…