3

根据我的阅读,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

4 回答 4

7

你做事的顺序不对。

  1. resize到您希望缓冲区接受的最大大小。
  2. 存储数据(必须小于向量大小)。
  3. resize到真实的数据大小。

您的“数据消失”问题是因为当您第一次复制数据时,您的向量没有大小容量(即预先保留的内存而没有实际使用它来保存数据)。再次时reserve,大小仍然为 0,因此向量可以自由优化数据副本,因为它知道它必须只保留第一个size()元素(即 0)。

换句话说:

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

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

于 2013-05-02T13:45:30.167 回答
3

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

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

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

于 2013-05-02T13:43:04.493 回答
0

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

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

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

于 2013-05-02T13:43:28.997 回答
0

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

Reserve() 不会减少先前保留的容量。这就是为什么在最后一行中您仍然看到 50,但您将其减少到 20。

于 2013-05-02T13:49:32.887 回答