• 【C++常见八股2】vector 的 push_back 扩容问题 | char *和 char [] 区别


    1、vector 的 push_back 扩容机制为什么不考虑在尾元素后面的空间申请内存?

    参考:https://www.zhihu.com/question/384869006

    C++ 标准库容器的动态内存分配是交予分配器(Allocator)类处理的,故而分配器提供什么接口,标准库容器的内存操作才能用什么。

    std::allocator 与 C++ 语言核心的问题另一方面,即使上述增强分配器的设计进入标准库,容器所用的默认分配器 std::allocator 也不一定能从中受益。原因是 std::allocator 的 allocate 与 deallocate 分别包装全局的分配函数 ::operator new 与解分配函数 ::operator delete ,这些函数是 C++ 语核所要求的,而且可以被用户替换。这使得目前不一定有机制使 std::allocator 支持原位收缩/扩张或自动重新分配。

    虽然 realloc 可以实现指定位置分配内存,但是来自 C 的 realloc 是个对于 C++ 相当不灵活的函数:

    • realloc 有可能原地收缩/扩张,但也会静默地重新分配内存,用户无法选择。部分原因可能是有些 realloc 的会重新映射虚拟地址,而非原位扩张失败后再次分配
    • realloc 分配的内存只保证拥有基础对齐。 C11/C++17 具有对齐内存分配函数, realloc 却没有一个处理对齐的增强版本。

    目前 C++ 的对象模型还不允许直接把非可平凡复制的类型的对象逐位移动到另一个位置,同时将原位置的对象视为已死亡。
    考虑到以上问题, realloc 本身可能不太适合适配到泛型的分配器中。不过类似的静默重分配功能(有可能利用虚拟地址的重映射)可以作为一个可选的功能,是否使用取决于 vector 的元素类型。 basic_string 的元素类型必须是 POD ,所以不会遇到对象模型的问题。

    作者:暮无井见铃
    链接:https://www.zhihu.com/question/384869006/answer/1130101522
    来源:知乎

    从内存池的角度我是这么理解的,c++ stl中的alloc是两级空间配置器,二级空间配置器使用内存池技术,对较小的内存空间进行池化管理,因此扩容的时候,相当于由二级空间配置器在内存池中找一块较大的提前分配好的内存进行扩容来提升效率(因为这个空间是提前分配好的,可以避免在已分配尾部再进行扩容可能造成的开销以及可能分配失败的问题),而原有的空间会回收回内存池重复利用。换个角度讲,在内存池的背景下,如果在原有已分配内存尾部进行扩容,那内存池中的空间会越来越大,没有层次性。

    作者:胡适之啊胡适之_
    链接:https://www.nowcoder.com/?
    来源:牛客网

    2、char *和 char [] 区别

    char [] p1 是数组类型,char * p2 是指针类型,具体来说 p1 是 *const 即指针常量类型,p2 往往是 const * 即常量指针类型,所以下面操作是非法的:

    char p1[] = "hello";
    char *p2 = "world"; // 这里在 C++ 相当于 const *p2
    p1 = p2; // 非法
    *p2 = 't'; // 非法
    
    • 1
    • 2
    • 3
    • 4

    sizeof(p1) 是数组元素个数和元素类型字节数的乘积,sizeof(p2) 是指针类型的字节数,但是在传参时数组名会被转换为指向该数组下标为0的元素的指针,例如下面这个等效:

    size_t arrayLen(const int *arr);
    size_t arrayLen(const int arr[]);
    
    • 1
    • 2

    细微区别

    int temp[5];
    &temp+1; // &temp指向整个数组,因此+1后指向了数组末尾
    temp+1;  // temp指向数组第一个元素,+1后指向第二个元素
    
    const char *str1 = "hello"; // 字符串常量存储在只读区
    char str2[] = "hello";
    const char *str3 = "hello"; // str3 和 str1 值是一样的
    char str4[] = "hello";
    printf("%p\n%p\n%p\n%p\n", str1, str2, str3, str4);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    🔥 C++ 面经总结 🔥

  • 相关阅读:
    ONE 2.0应用场景解读 | 如何通过时序拓扑直观还原故障传导链路?
    S7-PLCSIM Advanced V4.0安装步骤和使用入门
    记录一次难搞的编译错误-- qml-rust 项目编译无法找到QtCore库的问题
    【C++】一文带你吃透string的模拟实现 (万字详解)
    Turtlebot2简单控制
    SpringBoot 整合Mybatis
    四个,Word提高效率小技巧
    【endnote】如何将参考文献放到想放的位置
    Hive案例
    CSS中backdrop-filter与fliter属性
  • 原文地址:https://blog.csdn.net/Miracle_ps/article/details/134036023