不能直接 new int[],因为栈需动态伸缩,而 new int[n] 分配固定大小数组,扩容必须重新分配、拷贝、释放;需手动实现扩容逻辑,初始容量建议4或8,扩容按1.5或2倍增长,delete[] 必须配对 new int[capacity],构造函数中 data = nullptr,析构函数判空再 delete[],push/pop 需严格检查 top_index 越界,pop 应返回 data[--top_index] 并处理空栈异常,拷贝构造与赋值必须深拷贝避免悬空指针,移动构造可偷指针提升效率,但需注意异常安全——扩容时 new 可能抛 bad_alloc,应先分配新内存再释放旧内存。

用指针手动管理栈内存时,为什么不能直接 new int[]?
因为栈需要动态伸缩,而 new int[n] 分配的是固定大小数组,扩容必须重新分配、拷贝、释放——这正是指针实现栈的核心难点。你得自己写扩容逻辑,否则一 push 就越界。
- 初始容量建议设为 4 或 8,避免频繁分配;每次扩容按 1.5 或 2 倍增长(
capacity = capacity * 2更易计算) -
delete[] data必须配对new int[capacity],漏掉就内存泄漏 - 构造函数里
data = nullptr,析构函数里判空再delete[],防止重复释放
push() 和 pop() 的边界检查怎么做才不出错?
出错多发生在没检查 top_index 越界:push 前要判断是否 top_index == capacity,pop 前必须确认 top_index > 0。返回值也容易错——pop 不该返回 void,否则无法拿到值;但也不能返回局部变量引用。
- push 先检查容量,不够就扩容再赋值:
data[top_index++] = value - pop 应返回
data[--top_index],不是data[top_index--](后者会返回旧值且索引错位) - 空栈 pop 时抛
std::runtime_error("stack is empty"),比静默崩溃更利于调试
拷贝构造和赋值运算符为什么必须深拷贝?
浅拷贝会让两个栈对象共享同一块 data 内存,一个析构后另一方的 data 就成悬空指针,后续访问必崩。所有涉及指针成员的类都绕不开这点。
- 拷贝构造:
data = new int[other.capacity]; memcpy(data, other.data, other.top_index * sizeof(int)); - 赋值运算符:先检查自赋值(
if (this == &other) return *this;),再释放当前data,再分配+拷贝 - 移动构造可偷指针:
data = other.data; other.data = nullptr;,避免拷贝开销
用 raw pointer 实现栈,哪些地方最容易被忽略?
最常漏的是异常安全:扩容时 new 可能抛 std::bad_alloc,如果在拷贝老数据中途失败,原栈状态已被破坏。标准库 std::stack 用 RAII 和容器保证强异常安全,手写指针栈很难做到。
- 扩容前先
int* new_data = new int[new_capacity],成功后再释放旧内存 - 拷贝老数据用
for循环而非memcpy(若未来改存非 POD 类型,memcpy 会跳过构造) -
top_index是下一个可用位置索引,不是当前栈顶下标——这个语义必须文档化或注释清楚,否则协作时极易误解
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











