我试图将解析出的文件名从正则表达式匹配转移到filesystem::path
对象列表。
我相信匹配是有效的,因为for_each
对于相同的迭代器和打印到控制台工作完美。但是,我在运行此代码时遇到了分段错误。我究竟做错了什么?我的lambda有错吗?
namespace fs = boost::filesystem;
std::forward_list<fs::path> results;
std::transform(std::sregex_iterator(file_data.begin(), file_data.end(), re),
std::sregex_iterator(), results.begin(),
[&](const std::smatch& m)->fs::path{
return root / fs::path(m[1].str());
});
GDB向我展示了这一行作为错误的地方:
path& operator=(const path& p)
{
m_pathname = p.m_pathname;
return *this;
}
更新:找到解决方案 - 使用back_inserter(results)
代替results.begin()
。但是,为什么呢?
答案 0 :(得分:6)
std::transform
算法的第三个参数应该是应该写入值的范围起点的迭代器。具体来说,它通过使用转换后的值覆盖迭代器指向的范围内的值来工作。这意味着实际上必须在那里覆盖值才能覆盖。在你的情况下,你写的是一个空的forward_list
,所以没有什么可写的,因此崩溃。
要解决此问题,请考虑使用back_inserter
替换最后一个参数,这将自动创建在生成值时所需的空间:
std::transform(std::sregex_iterator(file_data.begin(), file_data.end(), re),
std::sregex_iterator(),
back_inserter(results), // <--- This is new
[&](const std::smatch& m)->fs::path{
return root / fs::path(m[1].str());
});
更一般地说,据我所知,<algorithm>
中写入输出范围的所有算法都假设有可用于覆盖该范围的值。如果不是这种情况,请考虑使用back_inserter
或其他类型的插入迭代器,它将自动创建您需要的空间。
希望这有帮助!
答案 1 :(得分:2)
您的输出迭代器是一个简单的results.begin()
,可能是== results.end()
。这里的线索是在尝试分配结果时失败。
您要么找到back_inserter
,要么使用已经分配了足够空间的容器(只有在您知道提前转换了多少项目时才能使用)。
具体来说,请考虑第一个重载here的示例实现。
该行
*d_first++ = op(*first1++);
要求目标迭代器已经有效。如果按照建议== end()
,则整个操作都是非法的。