C++?Boost?CircularBuffer算法超詳細精講
提要
庫 Boost.CircularBuffer 提供了一個循環(huán)緩沖區(qū),它是一個具有以下兩個基本屬性的容器:
- 循環(huán)緩沖區(qū)的容量是恒定的,由您設置。當您調用成員函數(shù)(例如 push_back())時,容量不會自動更改。只有您可以更改循環(huán)緩沖區(qū)的容量。循環(huán)緩沖區(qū)的大小不能超過您設置的容量。
- 盡管容量不變,但您可以隨時調用 push_back() 將元素插入循環(huán)緩沖區(qū)。如果已達到最大大小并且循環(huán)緩沖區(qū)已滿,則將覆蓋元素。
當可用內存量有限并且您需要防止容器任意增長時,循環(huán)緩沖區(qū)是有意義的。另一個例子是連續(xù)數(shù)據(jù)流,隨著新數(shù)據(jù)的可用,舊數(shù)據(jù)變得無關緊要。通過覆蓋舊數(shù)據(jù)自動重用內存。
要使用 Boost.CircularBuffer 中的循環(huán)緩沖區(qū),請包含頭文件 boost/circular_buffer.hpp。此頭文件定義類 boost::circular_buffer。
示例 16.1。使用 boost::circular_buffer
#include <boost/circular_buffer.hpp> #include <iostream> int main() { typedef boost::circular_buffer<int> circular_buffer; circular_buffer cb{3}; std::cout << cb.capacity() << '\n'; std::cout << cb.size() << '\n'; cb.push_back(0); cb.push_back(1); cb.push_back(2); std::cout << cb.size() << '\n'; cb.push_back(3); cb.push_back(4); cb.push_back(5); std::cout << cb.size() << '\n'; for (int i : cb) std::cout << i << '\n'; }
boost::circular_buffer 是一個模板,必須用類型實例化。例如,示例 16.1 中的循環(huán)緩沖區(qū) cb 存儲 int 類型的數(shù)字。
循環(huán)緩沖區(qū)的容量是在實例化類時指定的,而不是通過模板參數(shù)。 boost::circular_buffer 的默認構造函數(shù)創(chuàng)建一個容量為零的緩沖區(qū)。另一個構造函數(shù)可用于設置容量。在示例 16.1 中,緩沖區(qū) cb 具有三個元素的容量。
可以通過調用 capacity() 來查詢循環(huán)緩沖區(qū)的容量。在示例 16.1 中,capacity() 將返回 3。
容量不等于存儲元素的數(shù)量。雖然 capacity() 的返回值是常數(shù),但 size() 返回緩沖區(qū)中元素的數(shù)量,這可能不同。 size() 的返回值始終介于 0 和循環(huán)緩沖區(qū)的容量之間。
示例 16.1 在第一次調用 size() 時返回 0,因為緩沖區(qū)不包含任何數(shù)據(jù)。調用 push_back() 三次后,緩沖區(qū)包含三個元素,第二次調用 size() 將返回 3。再次調用 push_back() 不會導致緩沖區(qū)增長。這三個新數(shù)字會覆蓋之前的三個數(shù)字。因此,size() 在第三次調用時會返回 3。
作為驗證,存儲的數(shù)字會在示例 16.1 的末尾寫入標準輸出。輸出包含數(shù)字 3、4 和 5,因為先前存儲的數(shù)字已被覆蓋。
示例 16.2。 boost::circular_buffer 的各種成員函數(shù)
#include <boost/circular_buffer.hpp> #include <iostream> int main() { typedef boost::circular_buffer<int> circular_buffer; circular_buffer cb{3}; cb.push_back(0); cb.push_back(1); cb.push_back(2); cb.push_back(3); std::cout << std::boolalpha << cb.is_linearized() << '\n'; circular_buffer::array_range ar1, ar2; ar1 = cb.array_one(); ar2 = cb.array_two(); std::cout << ar1.second << ";" << ar2.second << '\n'; for (int i : cb) std::cout << i << '\n'; cb.linearize(); ar1 = cb.array_one(); ar2 = cb.array_two(); std::cout << ar1.second << ";" << ar2.second << '\n'; }
示例 16.2 使用了其他容器中不存在的成員函數(shù) is_linearized()、array_one()、array_two() 和 linearize()。這些成員函數(shù)闡明了循環(huán)緩沖區(qū)的內部結構。
循環(huán)緩沖區(qū)本質上類似于 std::vector。因為開始和結束的定義很好,所以可以將向量視為傳統(tǒng)的 C 數(shù)組。也就是說,內存是連續(xù)的,第一個和最后一個元素總是在最低和最高的內存地址。但是,循環(huán)緩沖區(qū)不提供這樣的保證。
盡管談論循環(huán)緩沖區(qū)的開始和結束可能聽起來很奇怪,但它們確實存在。可以通過迭代器訪問元素,并且 boost::circular_buffer 提供了成員函數(shù),例如 begin() 和 end()。雖然使用迭代器時不需要關心開始和結束的位置,但使用常規(guī)指針訪問元素時情況會變得有點復雜,除非你使用 is_linearized()、array_one()、array_two()、和線性化()。
如果循環(huán)緩沖區(qū)的開頭位于最低內存地址,則成員函數(shù) is_linearized() 返回 true。在這種情況下,緩沖區(qū)中的所有元素從頭到尾連續(xù)存儲在不斷增加的內存地址中,并且可以像傳統(tǒng)的 C 數(shù)組一樣訪問元素。
如果 is_linearized() 返回 false,則循環(huán)緩沖區(qū)的開頭不在最低內存地址,示例 16.2 中就是這種情況。雖然前三個元素 0、1 和 2 完全按此順序存儲,但第四次調用 push_back() 將用數(shù)字 3 覆蓋數(shù)字 0。因為 3 是調用 push_back() 添加的最后一個元素,它現(xiàn)在是循環(huán)緩沖區(qū)的新端。現(xiàn)在開始是編號為 1 的元素,它存儲在下一個更高的內存地址。這意味著元素不再連續(xù)存儲在不斷增加的內存地址中。
如果循環(huán)緩沖區(qū)的末尾位于比開頭低的內存地址,則可以通過兩個傳統(tǒng)的 C 數(shù)組訪問元素。為了避免計算每個數(shù)組的位置和大小,boost::circular_buffer 提供了成員函數(shù) array_one() 和 array_two()。
array_one() 和 array_two() 都返回一個 std::pair,其第一個元素是指向相應數(shù)組的指針,第二個元素是大小。 array_one() 訪問循環(huán)緩沖區(qū)開頭的數(shù)組,array_two() 訪問緩沖區(qū)末尾的數(shù)組。
如果循環(huán)緩沖區(qū)被線性化并且 is_linearized() 返回 true,則也可以調用 array_two()。但是,由于緩沖區(qū)中只有一個數(shù)組,因此第二個數(shù)組不包含任何元素。
為了簡化問題并將循環(huán)緩沖區(qū)視為傳統(tǒng)的 C 數(shù)組,您可以通過調用 linearize() 強制重新排列元素。完成后,您可以使用 array_one() 訪問所有存儲的元素,而無需使用 array_two()。
Boost.CircularBuffer 提供了一個名為 boost::circular_buffer_space_optimized 的附加類。此類也在 boost/circular_buffer.hpp 中定義。盡管此類的使用方式與 boost::circular_buffer 相同,但它在實例化時不保留任何內存。相反,內存是在添加元素時動態(tài)分配的,直到達到容量為止。刪除元素會相應地釋放內存。 boost::circular_buffer_space_optimized 更有效地管理內存,因此在某些情況下可能是更好的選擇。例如,如果您需要一個大容量的循環(huán)緩沖區(qū),它可能是一個不錯的選擇,但您的程序并不總是使用完整的緩沖區(qū)。
到此這篇關于C++ Boost CircularBuffer算法超詳細精講的文章就介紹到這了,更多相關C++ Boost CircularBuffer內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C++實現(xiàn)LeetCode(53.最大子數(shù)組)
這篇文章主要介紹了C++實現(xiàn)LeetCode(53.最大子數(shù)組),本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下2021-07-07