C++实现Timsort报expression must have a constant value问题解决
C++ Timsort实现编译报错问题排查
问题背景
以下为C++实现的Timsort排序代码,该算法通过合并插入排序生成的有序子数组实现高效排序:
#include <iostream> #include <iomanip> #include <algorithm> using namespace std; const int RUN = 32; void insertionSort(int arr[], int left, int right) { for (int i = left + 1; i <= right; i++) { int temp = arr[i]; int j = i - 1; while (j >= left && arr[j] > temp) { arr[j + 1] = arr[j]; j--; } arr[j + 1] = temp; } } void merge(int arr[], int l, int m, int r) { // original array is broken in two parts // left and right array int len1 = m - l + 1, len2 = r - m; int left[len1], right[len2]; for (int i = 0; i < len1; i++) left[i] = arr[l + i]; for (int i = 0; i < len2; i++) right[i] = arr[m + 1 + i]; int i = 0; int j = 0; int k = l; // after comparing, we merge those two array // in larger sub array while (i < len1 && j < len2) { if (left[i] <= right[j]) { arr[k] = left[i]; i++; } else { arr[k] = right[j]; j++; } k++; } // copy remaining elements of left, if any while (i < len1) { arr[k] = left[i]; k++; i++; } // copy remaining element of right, if any while (j < len2) { arr[k] = right[j]; k++; j++; } } void timSort(int arr[], int n) { for (int i = 0; i < n; i += RUN) insertionSort(arr, i, min((i + RUN - 1), (n - 1))); for (int size = RUN; size < n; size = 2 * size) { for (int l = 0; l < n; l += 2 * size) { int m = l + size - 1; int r = min((l + 2 * size - 1), (n - 1)); if (m < r) merge(arr, l,m,r); } } } int main() { int arr[] = { 40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 }; int n = sizeof(arr) / sizeof(arr[0]); cout << n << endl; cout << "Array :" << endl; for (int i = 0; i < n; i++) { cout << setw(3) << arr[i]; } timSort(arr, n); cout << "\nAfter Timsort: " << endl; for (int i = 0; i < n; i++) { cout << setw(3) << arr[i]; } return 0; }
上述代码在部分在线运行环境可正常执行,但本地编译时报错:expression must have a constant value。
报错原因
- 报错触发点为merge函数内的
int left[len1], right[len2];代码行 - 以变量作为数组长度的写法属于变长数组(VLA),是C99标准特性,未被纳入任何C++官方标准
- 在线运行环境通常使用GCC/Clang编译器,默认开启了支持VLA的非标准扩展,因此可正常编译;本地编译器如MSVC,或开启了严格C++标准校验的编译环境不支持该非标准语法,因此抛出错误。
解决方案
方案1(推荐):使用std::vector替代变长数组
符合C++标准,无需手动管理内存,修改merge函数内数组声明代码:
将
int left[len1], right[len2];
替换为
// 头文件区域添加该声明 #include <vector> // merge函数内修改为以下代码 std::vector<int> left(len1); std::vector<int> right(len2);
也可写为:
std::vector<int> left, right; left.resize(len1); right.resize(len2);
方案2:使用动态内存分配
// merge函数内修改为以下代码 int *left = new int[len1]; int *right = new int[len2]; // 原有排序逻辑保持不变 // 函数结束前手动释放内存避免泄漏 delete[] left; delete[] right;
内容的提问来源于stack exchange,提问作者enl1ghtenment
相关产品推荐
相关产品推荐

