【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'; // 非法

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

size_t arrayLen(const int *arr);
size_t arrayLen(const int arr[]);

细微区别

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);

🔥 C++ 面经总结 🔥

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值