前端开发入门到精通的在线学习网站

网站首页 > 资源文章 正文

百度实习面试:std::vector的大小是多少?

qiguaw 2024-10-29 15:24:24 资源文章 17 ℃ 0 评论

std::vector的大小是多少?


我们经常使用vector,那么vector到底有多大呢?
我们通过一段代码来看看


#include <vector>
#include <iostream>


int main() {
    std::vector<int> emptyVec;
    std::cout << "Size of std::vector: " << sizeof(emptyVec) << " bytes" << std::endl;
    return 0;
}

上面这段代码

Windows环境Debug下输出32,Release下输出24

Centos环境输出是24


std::vector 类模板在 C++ STL 中的实现通常包含几个关键的私有成员变量,它们用于管理存储和访问元素所需的数据。这些成员包括:

一个指向当前存储区域起始位置的指针。

一个指向当前存储区域末尾(即下一个可写入位置)的指针。

一个指向存储区域结束(即分配的存储容量的末尾)的指针。

有时还包括一个表示当前元素数量的计数器。


由于 std::vector 是一个模板类,其对象的实际大小依赖于元素的类型和编译器的对齐规则。即使 std::vector 完全为空,它仍然需要存储上述管理信息。因此,即使没有存储任何元素,std::vector 本身也会占据一定量的内存。


我们看一下GCC的vector源码,可以看到这里面有三个指针作为成员变量,所以大小是三个指针的大小也就是24个字节。


三个指针分别表示:

目前使用空间的头

目前使用空间的尾

目前可用空间的尾


Windows环境Debug下多了8个字节,是因为在调试环境中,C++ 标准库(如 MSVC 的实现)可能会为 std::vector 添加额外的成员或元数据,以便提供更好的错误检测和调试支持。


对于vector有个知识点:

动态增加大小,不是在原空间后面接连续的新空间,因为无法保证原来的空间后面有足够的空间。所以vector是以原来大小的两倍重新申请一块较大空间,然后把原来的内容拷贝过来,之后再构造新元素。


对vector的任何操作,只要发生了动态配置,那么指向原来vector的所有迭代器就都失效了。在删除元素的时候,经常犯这个错误。


std::vector<int> vec = {1, 2, 3, 4, 5};
for (auto it = vec.begin(); it != vec.end(); ++it) 
{
    if (*it == 2) 
    {
        vec.erase(it);
    }
}


// 错误:可能未到达 `vec.end()`

上面的代码就是经典的一个删除元素错误。


问题分析

在初始状态下,it 指向 vec 的第一个元素,即 1。

当 *it == 2 时,循环体内执行 vec.erase(it)。这意味着当 it 指向 2 时,2 会被删除。

vec.erase(it) 会删除当前迭代器指向的元素,并返回一个新的迭代器,指向删除元素后的位置。

问题点:vec.erase(it) 被调用后,it 仍然是指向已删除元素的位置。但是,原始代码中并没有更新 it 的值。

接下来,++it 会使 it 指向 2 之后的元素。然而,由于 2 已经被删除,实际上 it 现在指向了一个不存在的位置。


举例说明

假设 std::vector<int> vec = {1, 2, 3, 4, 5}。

初始时,it 指向 1。

循环第一次迭代时,it 指向 1,条件不满足,it 指向 2。

循环第二次迭代时,it 指向 2,条件满足,2 被删除。

问题:此时 it 仍然指向 2 的位置,但是 2 已经被删除,因此 it 指向的位置实际上是无效的。

接下来的 ++it 使得 it 指向 2 之后的元素,即原本的 3 的位置。但是,由于 2 已经被删除,it 实际上指向了 4 的位置,跳过了原本的 3。


(执行删除后,原来的整个迭代器已经全部失效,vec现在变成了{1,3,4,5})


正确做法如下:

std::vector<int> vec = {1, 2, 3, 4, 5};
for (auto it = vec.begin(); it != vec.end();) 
{
    if (*it == 2) 
    {
        it = vec.erase(it);
    } else 
    {
        ++it;
    }
}

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表