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

C++中使用copy_if复制deque到list后无法正常打印的原因

问题分析与解决方案

嘿,我一眼就看出你遇到的问题核心了——你在使用std::copy_if往list里复制元素时,犯了一个STL算法的常见错误!

问题根源

std::copy_if(以及std::copy这类基于输出迭代器的算法)的核心逻辑是仅对迭代器指向的位置进行赋值操作,它不会自动为目标容器分配空间或插入新元素。

你的代码里,list<string> l初始化后是空容器,l.begin()指向的是容器的尾后位置(没有实际元素的无效位置)。直接把这个迭代器传给copy_if,相当于往一片无效内存区域赋值,这属于未定义行为。你能通过l.front()看到内容完全是巧合——运气好的话内存没被覆盖,但这种情况完全不可靠,换个编译环境或运行时机可能直接崩溃。

你贴的copy_if语义实现也能佐证这一点:它只做*result = *first和++result,根本没有调用容器的插入方法。

修复方案

有两种简单可靠的方式解决这个问题:

方案1:使用std::back_inserter(推荐)

std::back_inserter会返回一个插入迭代器,当算法对它赋值时,它会自动调用容器的push_back()方法,把元素插入到容器末尾。你只需要修改copy_if的第三个参数:

copy_if(d.begin(),d.end(),back_inserter(l), [](const string& s){
  return s.find("fooparticle")!= string::npos;
});

这个方法不需要提前知道要插入多少元素,也不会产生额外遍历,是最简洁高效的方式。

方案2:提前为list分配空间

如果你确实想使用l.begin()作为输出迭代器,需要先让list拥有足够的元素空间:

// 先统计deque中符合条件的元素数量
int match_count = count_if(d.begin(), d.end(), [](const string& s){
  return s.find("fooparticle") != string::npos;
});
// 调整list的大小,创建对应数量的默认构造元素
l.resize(match_count);
// 现在可以安全地使用l.begin()了
copy_if(d.begin(),d.end(),l.begin(), [](const string& s){
  return s.find("fooparticle")!= string::npos;
});

不过这种方法需要额外遍历一次deque统计数量,对于list这种链表容器来说,resize的意义不大,所以更推荐第一种方案。

修复后的效果

修改后,你再运行代码,First try和Second try的打印都会正常输出符合条件的fooparticle 10 11.4,不会再出现空输出的情况。

额外小提示

你读取文件的循环也有个小问题:while(in)会在最后一次读取失败后,仍然把空字符串push_back到deque里。可以改成:

while(getline(in,tmp_str)){
  d.push_back(tmp_str);
}

这样只有当读取成功时才会添加元素,避免deque末尾多一个空字符串。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:46:40