C++编译报错:expression must have a constant value问题求助
滑动窗口最大值代码的编译错误分析与解决
问题描述
以下是实现滑动窗口最大值的C++代码:
#include <iostream> #include <deque> using namespace std; void printKMax(int arr[], int n, int k) { deque<int>dq; int i; for (i = 0; i < k; i++) { while (dq.back() < arr[i]) { dq.pop_back(); dq.push_back(i); } } for (; i < n; i++) { cout << dq.front(); while (dq.front() <= i - k) { dq.pop_front(); } while (dq.back() < arr[i]) { dq.pop_back(); dq.push_back(i); } } cout << dq.front(); } int main() { int t; cin >> t; while (t > 0) { int n, k; cin >> n >> k; int i; int arr[n]; for (i = 0; i < n; i++) cin >> arr[i]; printKMax(arr, n, k); t--; } return 0; }
编译时int arr[n];行出现以下错误:
- expression must have a constant value
- the value of variable cannot be used as a constant
- expression did not evaluate to a constant
错误原因
标准C++不支持变长数组(Variable-Length Array, VLA),n是程序运行时通过输入获取的变量,不是编译期能确定的常量,因此不能用来定义数组的大小。部分编译器(如GCC)将变长数组作为非标准扩展支持,但这会导致代码失去可移植性,换用其他编译器(如MSVC)就会触发上述编译错误。
解决方法
方法1:使用std::vector(推荐)
std::vector是标准C++提供的动态数组容器,完全符合标准,且无需手动管理内存。修改步骤:
- 添加
<vector>头文件; - 将
int arr[n];替换为vector<int> arr(n);。
修改后的main函数部分:
#include <iostream> #include <deque> #include <vector> // 新增头文件 using namespace std; // ... printKMax函数不变 ... int main() { int t; cin >> t; while (t > 0) { int n, k; cin >> n >> k; int i; vector<int> arr(n); // 替换变长数组 for (i = 0; i < n; i++) cin >> arr[i]; printKMax(arr.data(), n, k); // 用data()获取底层数组指针 cout << endl; // 可选:每次测试用例后换行,输出更清晰 t--; } return 0; }
方法2:动态内存分配(new/delete)
手动申请堆内存,注意使用完后要释放避免内存泄漏:
int main() { int t; cin >> t; while (t > 0) { int n, k; cin >> n >> k; int i; int* arr = new int[n]; // 动态分配内存 for (i = 0; i < n; i++) cin >> arr[i]; printKMax(arr, n, k); delete[] arr; // 释放内存 cout << endl; t--; } return 0; }
方法3:启用编译器扩展(不推荐)
如果必须使用变长数组,可以在支持该扩展的编译器中开启对应选项(如GCC添加-std=gnu++11或更高版本参数),但此方法会导致代码无法在标准C++编译器中编译,不建议使用。
额外:滑动窗口逻辑错误修正
原printKMax函数存在逻辑错误,即使编译通过也无法得到正确结果,需要修正:
- 双端队列存储的是数组索引,比较时应使用索引对应的数组值,而非索引本身;
- 操作队列前需判断队列是否为空,避免访问空队列的
back()或front()导致未定义行为; push_back(i)应放在while循环外部,否则每次弹出元素就会立即插入当前索引,逻辑混乱。
修正后的printKMax函数:
void printKMax(int arr[], int n, int k) { deque<int> dq; int i; for (i = 0; i < k; i++) { // 移除队列中所有比当前元素小的索引,确保队列头部是窗口最大值的索引 while (!dq.empty() && arr[dq.back()] < arr[i]) { dq.pop_back(); } dq.push_back(i); } for (; i < n; i++) { // 输出当前窗口的最大值 cout << arr[dq.front()] << " "; // 移除窗口外的索引 while (!dq.empty() && dq.front() <= i - k) { dq.pop_front(); } // 维护队列单调性 while (!dq.empty() && arr[dq.back()] < arr[i]) { dq.pop_back(); } dq.push_back(i); } // 输出最后一个窗口的最大值 cout << arr[dq.front()] << endl; }
内容的提问来源于stack exchange,提问作者Quang huynh
相关产品推荐
相关产品推荐

