Teach you how to implement buffer (1) - the concept and requirements of buffer in C++

written in front

The concept of buffer is huge. According to different scenarios, there are buffers with various functions, such as double buffer buffer and jitter buffer. The buffer mentioned in this article refers to a section of memory space used to access data, which is the most basic buffer. However, this is the most basic buffer, and the standard library in C++ does not provide a very general and complete buffer class (-_-!).

This series of articles will refer to webrtc CopyOnWriteBufferand introduce step by step how to implement such a buffer.

Implementation of buffer

static allocation

In our usual development, when a buffer is needed, the easiest way is to directly define an array, as follows:

//128字节的数组
uint8_t buffer[128]

This method is called a static array, the space is allocated on the stack, and a buffer with a fixed length of 128 bytes is generated. The length value is an estimate, and the space is not allocated according to the runtime of the program, but determined by the compiler, so it will cause space waste.

dynamic allocation

By newor mallocdynamically allocating a buffer, the advantage of this method is to allocate it when the program is running, which will not cause space waste. The disadvantage is also obvious, that is, you need to manually manage the buffer, which will cause memory leaks if you are not careful.

Manage buffers through smart pointers

When it comes to C++11, unique_ptrit can be used to replace the naked pointer to manage the dynamically allocated memory, so as to achieve the purpose of automatically releasing the memory

//在超出作用域时,会自动释放
std::unique_ptr <uint8_t[]> buffer(new uint8_t[128]);

But this kind of buffer is still too primitive (the essence is to manage buffer through pointer):

  1. The capacity is fixed, although it is dynamically allocated, it is more troublesome to expand the capacity
  2. Lack of necessary interfaces, such as judging whether the buffer is empty, obtaining the length of data in the buffer, etc.

vector instead of pointer

The buffer in the standard library vectorcan be used as a buffer, which can automatically manage memory, automatically expand capacity, and provide the necessary interface.

#include <vector>
#include <iostream>
int main() {
    
    
    std::vector<uint8_t> buffer;
    //代表一段数据
    uint8_t data1[3] = {
    
    1,2,3};
    buffer.assign(data1,data1+3);
    std::cout<<"size:"<<buffer.size()<<",capacity:"<<buffer.capacity()<<std::endl;
    //代表另外一段数据
    uint8_t data2[5] = {
    
    1,2,3,4,5};
    //会自动扩容
    buffer.assign(data2,data2+5);
    std::cout<<"size:"<<buffer.size()<<",capacity:"<<buffer.capacity()<<std::endl;
    
    for (auto i:buffer) {
    
    
        std::cout<<(uint32_t)i<<" ";
    }
}

In the above code, the buffer will automatically expand when it is data2put in buffer. vectorAlso provides size(), capaciy()and other basic interfaces. vectorThe passed data()method can get the pointer of the internal buffer.

Limitations of using vector as a buffer

vectorIt meets most of the requirements of being a buffer, but its interface still has limitations. For example, it does vectornot provide a method to add a piece of data assgin. Although there is a method, it vectorcopies a piece of data into it instead of adding it.

Implement your own buffer

The requirements of the buffer are described above, which can be summarized as follows:

  1. Dynamic memory allocation
  2. Automatic memory management
  3. Automatic expansion
  4. Provides an easy-to-use interface

vectorThe first three requirements are met. But the fourth is the most important. After all, it is simple and easy to use is the core requirement.

Guess you like

Origin blog.csdn.net/mo4776/article/details/126107614