1. circular buffer has two fundamental properties:
(1): The capacity of the circular buffer is constant and set by you. The capacity doesn't change automatically when you call a member function such as push_back(). Only you can change the capacity of the circular buffer. The size of the circular buffer can not exceed the capacity you set.
(2): Despite constant capacity, you call push_back() as often as you like to insert elements into the circular buffer. If the maximum size has been reached and the circular buffer is full, elements are overwritten.
2. using boost::circular_buffer
#include <boost/circular_buffer.hpp> #include <iostream> int main() { boost::circular_buffer<int> cb(3); std::cout << cb.capacity() << std::endl; std::cout << cb.size() << std::endl; cb.push_back(0); cb.push_back(1); cb.push_back(2); std::cout << cb.size() << std::endl; cb.push_back(3); cb.push_back(4); cb.push_back(5); std::cout << cb.size() << std::endl; for (int i : cb) { std::cout << i << std::endl; } return 0; }
boost::circular_buffer is a template and must be instantiated with a type. The capacity of the circular buffer is specified when instantiating the class, not through a template paramter. The default constructor of boost::circular_buffer creates a buffer with a capacity of zero elements. Another constructor is available to set the capacity. The capacity of a circular buffer can be queried by calling capacity(). The capacity is not equivalent to the number of stored elements. While the return value of capacity() is constant, size() returns the number of elements in the buffer, which may be different. The return value of size() will always be between 0 and the capacity of teh circular buffer.
2. various member functions of boost::circular_buffer
#include <boost/circular_buffer.hpp> #include <iostream> int main() { boost::circular_buffer<int> 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() << std::endl; boost::circular_buffer<int>::array_range ar1, ar2; ar1 = cb.array_one(); ar2 = cb.array_two(); std::cout << ar1.second << ";" << ar2.second << std::endl; for (int i : cb) { std::cout << i << std::endl; } cb.linearize(); ar1 = cb.array_one(); ar2 = cb.array_two(); std::cout << ar1.second << ";" << ar2.second << std::endl; return 0; }
A circular buffer is essentially comparable to std::vector. Because the beginning and end are well defined, a vector can be treated as conventional C array. That is, memory is contiguous, and the first and last elements are always at the lowest and highest memory address. However, a circular buffer does not offer such a guarantee.
The member function is_linearized() returns true if the beginning of the circular buffer is at the lowest memory address. In this case, all the elements in the buffer are stored consecutively from beginning to the end at increasing memory addresses, and elements can be accessed like a conventional C array.
If is_linearized() return false, the beginning of the circular buffer is not at the lowest memory address, which is the case as above. While the first three elements 0, 1 and 2 are stored in exactly this order, calling push_back() for the fourth time will overwrite the number 0 with the number 3. Becasue 3 is the last element added by a call to push_back(), it is now the new end of the circular buffer. The beginning is now the element with the number 1, which is stored at the next higher memory address. This means elements are no longer stored consecutively increasing memory addresses.
Both array_one() and array_two() return a std::pair whose first element si a pointer to the corrsponding array and whose second element is the size. array_onw() accesses the array at the beginning of the circular buffer, and array_two() accesses the array at the end of the buffer.
To simplify matters and treat the circular buffer as a conventional C array, you can force a rearrangement to the elements by calling linearize(). Once complete, you can access all stored elements using array_one(), and you don't need to use array_two().