vector::push_back先构造再拷贝/移动,emplace_back直接原地构造;clear()不改变capacity;operator[]越界是未定义行为;vector是特化陷阱,使用代理引用。

vector::push_back 和 vector::emplace_back 的区别在哪
关键不在“能不能加”,而在“怎么加”——push_back 先构造再拷贝/移动,emplace_back 直接在 vector 尾部原地构造。对简单类型(如 int)没差别;但对自定义类,尤其含多参数构造函数或移动开销大的对象,emplace_back 更高效且能绕过隐式转换限制。
-
push_back(MyClass{1, "hello"}):先临时构造MyClass对象,再调用移动构造函数插入 -
emplace_back(1, "hello"):直接以1和"hello"为参数,在 vector 内存中调用MyClass::MyClass(int, const char*) - 如果构造函数是
explicit的,push_back可能编译失败,而emplace_back仍可用
clear() 后 vector 的容量(capacity)会变吗
不会。clear() 只销毁所有元素、把 size() 置为 0,但底层分配的内存(即 capacity())保持不变。这是为了后续快速复用内存,避免频繁 realloc。
- 想真正释放内存,得配合 swap 技巧:
std::vector
(v).swap(v); - C++11 起可改用
shrink_to_fit(),但它只是请求(非强制),实现可忽略 - 反复
clear()+push_back()多次,capacity()通常只增不减,除非显式干预
用 operator[] 访问越界时会发生什么
行为未定义(UB)——不抛异常、不报错、不保证崩溃,但程序可能读到垃圾值、触发段错误,或看似正常却藏有隐患。这和 at() 完全不同。
-
v[i]:无边界检查,快但危险;调试时容易漏掉越界问题 -
v.at(i):带检查,越界抛std::out_of_range异常,适合开发/测试阶段 - 迭代器访问(如
v.begin() + i)同样不检查,越界后解引用也是 UB
vector 是不是真正的容器
不是。它是 C++ 标准库中一个特化陷阱:vector 不满足容器要求,内部用位压缩存储,operator[] 返回的是代理对象(std::vector),而非 bool&。
立即学习“C++免费学习笔记(深入)”;
- 不能取地址:
&v[0]编译失败 - 无法用于需要真实引用的场景,比如绑定到
bool&参数的函数 - 迭代器行为异常,
*it = true有效,但auto& x = *it会绑定到临时代理,修改无效 - 真要存布尔值且需标准容器语义,用
vector或deque
vector 的代理引用机制和 clear() 不缩容这两点——它们在逻辑正确性上不报错,却会在长期运行或跨平台部署时突然暴露问题。









