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

将std::vector拆分为指定大小子vector的可读实现及std::bad_alloc问题

解决std::vector拆分时的std::bad_alloc异常,附高可读性实现方案

嘿,我来帮你搞定这个问题!首先你遇到的std::bad_alloc异常,九成是因为你用std::copy的时候,目标子vector没有预先分配足够的内存空间就直接往里写了——std::copy可不会自动帮目标容器扩容,如果传入的vec.begin()指向的是空vector,或者size小于要复制的元素数量,就会触发内存访问越界,最终抛出bad_alloc。

接下来我给你几种高可读性的实现方式,既解决异常问题,又让代码清晰易懂:

方法一:用范围构造函数(最简洁直观)

直接利用vector的范围构造能力,每次从原vector中截取一段迭代器范围来创建子vector,完全不用手动处理内存和copy,代码可读性拉满:

#include <vector>
#include <iostream>
#include <iterator> // 用于std::next

std::vector<std::vector<int>> splitIntoChunks(const std::vector<int>& input, size_t chunkSize) {
    std::vector<std::vector<int>> chunks;
    
    for (size_t i = 0; i < input.size(); i += chunkSize) {
        // 计算当前chunk的结束位置,避免超出原vector末尾
        auto endIter = std::next(input.begin(), std::min(i + chunkSize, input.size()));
        // 直接用迭代器范围构造子vector,自动处理内存分配
        chunks.emplace_back(input.begin() + i, endIter);
    }
    
    return chunks;
}

// 测试你的示例输入
int main() {
    std::vector<int> cam = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};
    auto result = splitIntoChunks(cam, 5);
    
    // 打印验证结果
    for (const auto& chunk : result) {
        std::cout << "[";
        for (size_t j = 0; j < chunk.size(); ++j) {
            if (j != 0) std::cout << ", ";
            std::cout << chunk[j];
        }
        std::cout << "]\n";
    }
    return 0;
}

运行这段代码会直接输出你想要的结果:

[1, 2, 3, 4, 5]
[6, 7, 8, 9, 10]
[11, 12, 13, 14, 15]
[16, 17]

方法二:修复你原来的std::copy写法

如果你坚持想用std::copy,那必须确保目标子vector有足够的空间,这里给你两种修复方式:

方式A:预先给子vector分配内存

先计算当前chunk的大小,用resize预分配空间,再执行copy:

std::vector<std::vector<int>> splitIntoChunks(const std::vector<int>& input, size_t chunkSize) {
    std::vector<std::vector<int>> chunks;
    
    for (size_t i = 0; i < input.size(); i += chunkSize) {
        size_t currentChunkSize = std::min(chunkSize, input.size() - i);
        std::vector<int> subVec;
        subVec.resize(currentChunkSize); // 预先分配足够空间
        std::copy(input.begin() + i, input.begin() + i + currentChunkSize, subVec.begin());
        chunks.push_back(subVec);
    }
    
    return chunks;
}

方式B:用std::back_inserter自动扩容

back_inserter会自动调用子vector的push_back,不需要手动分配空间,更安全:

#include <iterator> // 必须包含这个头文件

std::vector<std::vector<int>> splitIntoChunks(const std::vector<int>& input, size_t chunkSize) {
    std::vector<std::vector<int>> chunks;
    
    for (size_t i = 0; i < input.size(); i += chunkSize) {
        auto endIter = std::next(input.begin(), std::min(i + chunkSize, input.size()));
        std::vector<int> subVec;
        std::copy(input.begin() + i, endIter, std::back_inserter(subVec));
        chunks.push_back(subVec);
    }
    
    return chunks;
}

为什么你的原代码会抛出bad_alloc?

假设你原来的代码是类似这样的:

// 错误示例!
std::vector<int> vec;
std::copy(cam.begin() + start, cam.begin() + end + 1, vec.begin());

这里vec是空的,vec.begin()指向的是未初始化的内存地址,std::copy试图往这个位置写入元素,会直接触发内存访问越界,进而导致bad_alloc异常(或者直接崩溃,取决于编译器和系统)。

总结一下,最推荐的是方法一的范围构造函数写法,代码简洁、可读性高,还能避免手动内存管理的错误。

内容的提问来源于stack exchange,提问作者T. Swiz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 20:57:56