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

使用initializer list在堆上初始化vector避免栈溢出

问题分析与解决方案

一、初始化列表的差异原因

直接给栈上空vector赋值大初始化列表时触发“too many values in initializer list”,但map中的vector能正常运行,核心原因是:

  • 栈上vector赋值时,编译器会先在栈上创建临时的初始化列表元素数组,当元素数量过多超出栈默认容量(通常几MB)时,就会触发错误;而map的节点存储在堆上,vector的内部数据也在堆中,赋值时临时数组的处理逻辑不会受到栈容量限制。

二、解决栈溢出的简洁方案

核心思路是避免在栈上创建过大的临时初始化列表数组,让vector直接在堆上构建数据,以下是几种可行方式:

方式1:用emplace直接构造map元素

跳过临时对象的栈上创建,直接在堆上构造vector:

#include <map>
#include <vector>
#include <string>

struct IVector2 {
    int x;
    int y;
};

struct animation_frame_t {
    IVector2 position;
    IVector2 size;
};

std::map<std::string, std::vector<animation_frame_t>> animations;

void initAnimations() {
    animations.emplace("boss_andromeda_attack_", std::vector<animation_frame_t>{
        {{303,101},{100,100}}, {{606,101},{100,100}}, {{606,0},{100,100}},
        {{505,909},{100,100}}, {{505,808},{100,100}}, {{505,707},{100,100}},
        // ... 剩余帧数据
    });

    // 也可配合insert+std::move减少拷贝
    animations.insert({
        "boss_andromeda_breathing_",
        std::vector<animation_frame_t>{
            {{303,909},{100,100}}, {{303,808},{100,100}},
            // ... 剩余帧数据
        }
    });
}

方式2:显式构造vector再赋值

显式指定vector构造,让编译器优先在堆上处理初始化数据:

void initAnimations() {
    animations["boss_andromeda_death_"] = std::vector<animation_frame_t>{
        {{303,0},{100,100}}, {{202,909},{100,100}},
        // ... 剩余帧数据
    };
}

方式3:静态常量存储动画数据

如果动画数据固定不变,将其声明为静态常量,数据会存储在全局数据区,完全避开栈:

namespace AnimationData {
    static const std::vector<animation_frame_t> boss_andromeda_attack = {
        {{303,101},{100,100}}, {{606,101},{100,100}},
        // ... 剩余帧数据
    };
    // 其他动画数据同理定义
}

void initAnimations() {
    animations["boss_andromeda_attack_"] = AnimationData::boss_andromeda_attack;
}

方式4:从外部文件加载(适合超大量数据)

4万行硬编码数据会导致编译慢、二进制体积大,建议将数据存为JSON/CSV格式,运行时从文件加载:

// 示例伪代码(需引入第三方JSON库,如nlohmann/json)
#include <fstream>
#include <nlohmann/json>

void loadAnimationsFromFile(const std::string& path) {
    std::ifstream file(path);
    nlohmann::json j;
    file >> j;

    for (const auto& [key, frames] : j.items()) {
        std::vector<animation_frame_t> vec;
        vec.reserve(frames.size());
        for (const auto& frame : frames) {
            vec.push_back({
                {frame["position"]["x"], frame["position"]["y"]},
                {frame["size"]["x"], frame["size"]["y"]}
            });
        }
        animations[key] = std::move(vec);
    }
}

三、核心原理总结

std::vector内部数据本身是堆分配的,但大初始化列表赋值时,编译器可能先在栈上创建临时元素数组,触发栈溢出。通过显式构造、emplace/insert、静态常量或外部加载,均可绕过栈上临时数组的创建,直接在堆或全局区处理数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 03:40:16