正确的方法来设置std :: vector的大小

时间:2013-05-02 13:36:26

标签: c++ stl stdvector

根据我的阅读,std::vector是与c函数接口时使用的适当结构,需要连续的内存字节数组。但是我想知道如何在某些情况下确定数组的大小

我写了一个小样本程序来说明我的意思。

int main(int argc, char *argv[])
{
    std::vector<unsigned char>v;
    unsigned char p[1024];

    sprintf((char*)&p[0], "%10d", 10);
    cout << "Size: " << v.size() << " Length: " << v.capacity() << endl;
    v.reserve(30);
    cout << "Size: " << v.size() << " Length: " << v.capacity() << endl;
    memcpy(&v[0], &p[0], 20);
    cout << "Size: " << v.size() << " Length: " << v.capacity() << endl;
    v.reserve(50);
    cout << "Size: " << v.size() << " Length: " << v.capacity() << endl;
    v.reserve(0);
    cout << "Size: " << v.size() << " Length: " << v.capacity() << endl;
    v.resize(20);
    cout << "Size: " << v.size() << " Length: " << v.capacity() << endl;
    v.resize(0);
    cout << "Size: " << v.size() << " Length: " << v.capacity() << endl;

    return 0;
}

输出(不太令人惊讶):

Size: 0 Length: 0
Size: 0 Length: 30
Size: 0 Length: 30
Size: 0 Length: 50
Size: 0 Length: 50
Size: 20 Length: 50
Size: 0 Length: 50

我这样做的原因是,因为我保留了一定大小的缓冲区,然后通过recv()将此内存传递给套接字。由于我必须将内存作为指针传递,因此无法根据recv返回的内容调整向量大小。 现在当收到的字节数小于缓冲区时,我会认为我可以以某种方式调整向量的大小,所以当我传回它时,调用者可以做v.size()和元素的数量又是由接收返回。

当我查看上面示例中的数据时,使用resize()时,正确调整了缓冲区的大小,但数据已消失。那么我真的必须将内存单独复制到一个新的向量中才能获得正确的大小吗?这听起来像是一个非常不必要的开销。或者是否有某种方法可以告诉向量当前应该保留多少个元素?

4 个答案:

答案 0 :(得分:6)

你正在以错误的顺序做事。

  1. resize到您希望缓冲区接受的最大尺寸。
  2. 存储数据(必须小于矢量大小)。
  3. resize到实际数据大小。
  4. 您的“数据消失”问题是因为当您第一次复制数据时,您的向量只有大小的容量(即预先保留的内存而不实际使用它来保存数据)。再次reserve时,大小仍为0,因此向量可以自由地优化数据副本,因为它知道它必须只保留第一个size()元素(即0)。

    换句话说:

    • capacity() =您可以在不触发重新分配的情况下在向量中放入多少数据。
    • size() =您实际使用了多少数据(并且该向量仅在重新分配时保留 数据)

    更重要的是,访问其当前size()之后的向量元素是未定义行为(它可能看起来与整数类型一起使用,但考虑未初始化对象会发生什么......)。不要那样做。

答案 1 :(得分:3)

recv直接进入缓冲区,类似于:

std::vector< unsigned char > buffer( 1024 );
buffer.resize( recv( &buffer[0], buffer.size() ) );

根据recv是否可以返回错误代码,您可能需要在调整大小之前进行检查。

答案 2 :(得分:0)

v.reserve(n)将容量设置为n

m = recv(s,&v[0],n,0)

v.resize(m)将矢量大小设置为recv得到的值。

答案 3 :(得分:0)

当您从vector的缓冲区第一个字节开始将某些内容复制到内存位置时 - 该向量不会知道这一点,并且不会更新其内部大小计数器。使用vector的assign()或insert()方法将缓冲区复制到向量。

reserve()不会降低以前保留的容量。这就是为什么在最后一行中你仍然看到50但是你把它减少到20。