如何有效地处理像C缓冲区这样的std :: vector?

时间:2015-06-19 09:46:37

标签: c++ c++11 stl

使用C缓冲区,我经常这样做:

BYTE buffer[MAX_SIZE];
int dataSize = 0;

while (appRunning()) 
{
    dataSize += Receive(buffer + dataSize, MAX_SIZE - dataSize);

    int processedSize = ProcessBuffer(buffer, dataSize);
    ASSERT(processedSize <= dataSize);
    dataSize -= processedSize;
    memmove(buffer, buffer + processedSize, dataSize);
};

是否可以使用std::vector而不会失去太多性能?

编辑: 我找到了一种用std::vector替换原始C缓冲区的方法。

std::vector<BYTE> vbuf;
vbuf.reserve(MAX_SIZE); // allocated at once

while (appRunning()) 
{
    int pendingSize = GetPendingDataSize(); // from a socket
    if (pendingSize > vbuf.capacity())
        pendingSize = vbuf.capacity();

    vbuf.resize(pendingSize);
    int recvSize = Receive(vbuf.data(), vbuf.size());
    ASSERT(recvSize < vbuf.size());
    int processedSize = ProcessBuffer(vbuf.data(), vbuf.size());
    std::rotate(vbuf.begin(), vbuf.begin() + processedSize, vbuf.end());
    vbuf.resize(vbuf.size() - processedSize);
};

实际上,在我的实际使用中,接收数据和处理数据可以在多线程中完成。因此,通过使用向量,我不需要手动管理缓冲区的分配,数据大小和缓冲区容量。 与C缓冲区相比,这里的性能损失是vbuf.resize()次调用。但我认为惩罚是微不足道的。 感谢任何更好的方式。

5 个答案:

答案 0 :(得分:1)

从C ++ 11开始,C数组的大部分部分被std::array取代:

std::array<BYTE, MAX_SIZE> buffer;

它只是C数组的一个薄包装器。因此,从性能角度来看,你不会失去任何东西。然而,有更好的工作。

但是和C数组一样,它们只适用于编译时已知大小的固定时间数组。无法调整它们的大小。但是如果我正确地阅读了你的问题,你就不需要那么多的灵活性了。

答案 1 :(得分:1)

通过TCP连接接收消息时,缓冲区中的最后一条消息可能不完整。处理完完整的消息后,人们通常只会memmove将最后一条未完成的消息发送到缓冲区的开头。

另一种策略是使用“智能”环形缓冲区来避免memmove,并且还避免数据在环形缓冲区上回绕,从而造成不连续性。要创建“智能”环形缓冲区,请使用mmap为缓冲区分配内存,并两次映射页面的相同区域,并且两次之间没有间隙。这种从缓冲区末尾读取数据的方式将从头开始继续读取,从而避免了使用常规环形缓冲区时固有的不连续性。


为网络缓冲区使用std::vector不太理想,因为调整向量的大小会初始化其元素,这些元素随后会被recv调用覆盖。此类缓冲区不需要初始化。

答案 2 :(得分:0)

如果你想要类似于C的行为(也就是说,你想保证向量不会自由或为底层向量分配更多内存),一个很好的解决方案是使用Boost's static_vector。它静态地分配底层缓冲区,但否则它就像一个普通的向量。

boost::static_vector<BYTE, MAX_SIZE> buffer;

但是,对于此类活动,您还可以查看std::queueboost::cirular_buffer,看看其中一项是否符合您的需求。

答案 3 :(得分:0)

完全可以用std::vector或等效地std::array替换它。您不需要调整矢量的大小,因此也不需要。

std::vector<BYTE> buffer(MAX_SIZE);
BYTE * start = buffer.data();
int dataSize = 0;

while (appRunning()) 
{
    dataSize += Receive(start, MAX_SIZE - dataSize);

    int processedSize = ProcessBuffer(buffer.data(), dataSize);
    ASSERT(processedSize <= dataSize);
    dataSize -= processedSize;
    start = std::copy_n(buffer.data() + processedSize, dataSize, buffer.data());
};

答案 4 :(得分:-1)

从内存写入,请检查它是否适合您:

std::vector<BYTE> buffer;
buffer.reserve(MAX_SIZE);
int dataSize = 0;

while (appRunning()) 
{
    dataSize += Receive(&buffer[0] + dataSize, MAX_SIZE - dataSize);

    int processedSize = ProcessBuffer(&buffer[0], dataSize);
    ASSERT(processedSize <= dataSize);
    dataSize -= processedSize;
    memmove(&buffer[0], &buffer[0] + processedSize, dataSize);
};