C++非静态数据成员初始化警告及栈代码转动态内存的技术问询
解决你的C++栈相关问题
咱们先搞定第一个编译警告的问题。
一、编译警告的解决方法
你看到的 non-static data member initializers only available with -std=c++11 or -std=gnu++11 警告,原因很简单:在C11标准之前,类里的非静态成员变量(比如你写的int sizee=0;)不能直接在类定义里初始化,这个特性是C11才引入的。
有两种办法解决:
- 办法1:编译时指定C++标准版本
如果你用g或者clang编译,只要在编译命令里加上-std=c++11(或者更高版本,比如-std=c++17,推荐用新一点的标准,功能更全)就行。比如:g++ your_stack_code.cpp -std=c++17 -o stack_program - 办法2:把初始化移到构造函数里
如果你不想改编译参数,就把sizee的初始化放到类的构造函数中,去掉类里的int sizee=0;,然后添加构造函数:class tStack{ int STACK[MAX]; int sizee; // 去掉这里的=0 public: // 构造函数初始化sizee tStack() : sizee(0) {} // 后面的函数保持不变... };
二、改成动态内存版本的栈
原来的栈用固定大小的数组STACK[MAX],最大容量被MAX限制死了,动态版本可以让栈根据需要自动扩容,灵活很多。我给你改好的代码,顺便补上你没写完的push函数,还加了扩容逻辑:
#include <iostream> #include <stdexcept> // 推荐用std::exception代替字符串抛出,更规范 using namespace std; class tStack{ private: int* STACK; // 动态分配的数组指针,替代原来的固定数组 int sizee; // 当前栈里的元素个数 int capacity; // 当前栈的最大容量 public: // 构造函数:默认初始容量设为20,也可以让用户指定 tStack(int init_capacity = 20) : sizee(0), capacity(init_capacity) { // 分配初始内存 STACK = new int[capacity]; } // 析构函数:必须释放动态分配的内存,不然会内存泄漏 ~tStack() { delete[] STACK; } // 禁止拷贝构造和赋值运算符,避免浅拷贝导致的内存问题 tStack(const tStack&) = delete; tStack& operator=(const tStack&) = delete; // 判断栈是否为空 bool empty(){ return sizee == 0; } // 获取栈顶元素(注意:栈顶是最后一个元素,索引是sizee-1,原来的代码这里写错了) int val(){ if (empty()) { throw runtime_error("Stack is empty"); // 用标准异常更规范 } return STACK[sizee - 1]; } // 弹出栈顶元素 int pop(){ if (empty()) { throw runtime_error("Stack is empty"); } return STACK[--sizee]; } // 压入元素,自动扩容 void push(int value){ // 如果栈满了,就扩容(这里用翻倍的方式,保证 amortized O(1) 的时间复杂度) if (sizee == capacity){ int new_capacity = capacity * 2; int* new_stack = new int[new_capacity]; // 把旧数组的元素拷贝到新数组 for (int i = 0; i < sizee; ++i){ new_stack[i] = STACK[i]; } // 释放旧内存,更新指针和容量 delete[] STACK; STACK = new_stack; capacity = new_capacity; } // 压入新元素 STACK[sizee++] = value; } // 可选:获取当前栈的大小和容量 int get_size() const { return sizee; } int get_capacity() const { return capacity; } }; // 测试代码示例 int main(){ tStack s; s.push(10); s.push(20); cout << "栈顶元素:" << s.val() << endl; // 输出20 cout << "弹出元素:" << s.pop() << endl; // 输出20 cout << "当前栈大小:" << s.get_size() << endl; // 输出1 return 0; }
几个关键说明:
- 内存管理:必须写析构函数
~tStack()来释放STACK的内存,不然程序结束后这块内存不会被回收,造成内存泄漏。 - 避免浅拷贝:我禁用了拷贝构造和赋值运算符,因为默认的浅拷贝会让两个
tStack对象指向同一块内存,释放时会重复释放导致程序崩溃。如果需要支持拷贝,你得自己实现深拷贝版本。 - 自动扩容:当栈里的元素个数等于容量时,把容量翻倍,重新分配内存并拷贝旧元素,这样栈就不会有固定大小的限制了。
- 异常处理:我把原来的字符串抛出改成了
std::runtime_error,这是C++标准的异常类型,比抛出字符串更规范,也更容易捕获和处理。
内容的提问来源于stack exchange,提问作者new123321
相关产品推荐
相关产品推荐

