You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求更多在栈上分配任意空间的非标准跨编译器实现方案

在C++ constexpr函数中模拟GCC变长数组(VLA)行为的跨编译器方案

目前GCC支持在C++ constexpr函数中使用C变长数组(VLA),这是一个非标准扩展,但能实现预期的可变大小数组需求。为了兼容其他编译器(如Clang、MSVC),我已经实现了基于std::unique_ptr的标准降级方案,同时还总结了其他可行的跨编译器替代方案。

已实现的std::unique_ptr降级方案

该方案通过条件编译区分GCC和其他编译器,在非GCC环境下用堆分配的智能指针模拟VLA的使用方式:

class Integer {
private:
    int i;

public:
    constexpr
    Integer(const int& _t = 10)
    : i(_t)
    { }

    constexpr int
    get(void) const {
        return i;
    }
};

#if defined(__GNUC__) && !defined(__clang__)
#define XALLOC(type, name, count) type name[count]
#else
#include <memory>
#define XALLOC(type, name, count) std::unique_ptr<type[]> __##name(new type[count]); type* name = &__##name[0]
#endif

constexpr
int t(int num) {
    XALLOC(Integer, i, num);
    return i[0].get();
}

constinit int nu = t(10);

int main(int argc, const char *argv[]) {
    return t(0);
}

其他跨编译器兼容方案

方案1:C++20 constexpr std::vector(推荐)

C20开始std::vector支持constexpr构造与操作,对于支持C20的编译器(Clang 15+、MSVC 2022+),可以直接用std::vector替代VLA,既符合标准又能在constexpr中使用:

#include <vector>

#if defined(__GNUC__) && !defined(__clang__)
#define XALLOC(type, name, count) type name[count]
#elif __cplusplus >= 202002L
#define XALLOC(type, name, count) constexpr std::vector<type> name(count)
#else
#include <memory>
#define XALLOC(type, name, count) std::unique_ptr<type[]> __##name(new type[count]); type* name = &__##name[0]
#endif

constexpr int t(int num) {
    XALLOC(Integer, i, num);
    return i[0].get();
}

方案2:编译期静态数组+运行期动态分配的混合方案

如果数组大小在编译期可确定,优先使用std::array或静态数组;仅在运行期大小不确定时使用动态分配,结合if constexpr实现分支:

#include <array>
#include <memory>

template<int Num>
constexpr int t_constexpr() {
    std::array<Integer, Num> i;
    return i[0].get();
}

int t_runtime(int num) {
    std::unique_ptr<Integer[]> i(new Integer[num]);
    return i[0].get();
}

constexpr int t(int num) {
    if constexpr (std::is_constant_evaluated()) {
        // 编译期调用时要求num是常量表达式
        return t_constexpr<num>();
    } else {
        return t_runtime(num);
    }
}

constinit int nu = t(10); // 编译期执行
int main(int argc, const char *argv[]) {
    return t(argc); // 运行期执行
}

方案3:运行期使用alloca(仅非constexpr场景)

alloca可以在栈上分配可变大小内存,性能优于堆分配,但不能在constexpr中使用,且存在栈溢出风险,仅适合运行期非constexpr的场景:

#include <cstdlib>
#include <memory>

#if defined(__GNUC__) && !defined(__clang__)
#define XALLOC(type, name, count) type name[count]
#else
#define XALLOC(type, name, count) type* name = static_cast<type*>(alloca(sizeof(type) * count)); \
    std::uninitialized_default_construct_n(name, count)
#endif

// 注意:此版本的t函数不能是constexpr
int t(int num) {
    XALLOC(Integer, i, num);
    return i[0].get();
}

内容的提问来源于stack exchange,提问作者user23112128

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 03:00:17