我有以下代码(将字符串拆分为一个向量),它在for_each循环的第二次迭代中给出了段错误:
std::string command = "Something something something";
std::sregex_token_iterator splitter {command.begin(), command.end(), std::regex{"\\s+"}, -1};
std::sregex_token_iterator splitter_end;
std::for_each(splitter, splitter_end, [&](std::ssub_match sm) {
cmd.push_back(sm.str());
});
试图理解发生了什么,我将正则表达式的声明分离为命名变量并开始工作:
std::string command = "Something something something";
std::regex rx {"\\s+"};
std::sregex_token_iterator splitter {command.begin(), command.end(), rx, -1};
std::sregex_token_iterator splitter_end;
std::for_each(splitter, splitter_end, [&](std::ssub_match sm) {
cmd.push_back(sm.str());
});
任何人都可以向我解释这个吗?
答案 0 :(得分:4)
我知道答案,但我不喜欢它。我认为这可能是铿锵的缺陷。
std::sregex_token_iterator
正在保存指向正则表达式的指针。
在第一个版本中,匿名std::regex
对象在构造splitter
后被破坏。这使splitter
指向内存中的释放空间。
在第二个版本中,rx
将一直存在,直到阻止结束。这使splitter
指向正确的对象。
std::regex_token_iterator
构造函数
template <class _BidirectionalIterator, class _CharT, class _Traits>
regex_token_iterator<_BidirectionalIterator, _CharT, _Traits>::
regex_token_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b,
const regex_type& __re, int __submatch,
regex_constants::match_flag_type __m)
: __position_(__a, __b, __re, __m),
_N_(0),
__subs_(1, __submatch)
{
__init(__a, __b);
}
构建__position_
类型的std::regex_iterator
:
template <class _BidirectionalIterator, class _CharT, class _Traits>
regex_iterator<_BidirectionalIterator, _CharT, _Traits>::
regex_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b,
const regex_type& __re, regex_constants::match_flag_type __m)
: __begin_(__a),
__end_(__b),
__pregex_(&__re),
__flags_(__m)
{
_VSTD::regex_search(__begin_, __end_, __match_, *__pregex_, __flags_);
}
这是将__re
的地址存储为指针。 __re
超出范围后,__re
被解除__position_
会留下悬空指针。
最后的注释
以下作品:
std::string command = "Something something something";
std::for_each(std::sregex_token_iterator{command.begin(), command.end(), std::regex{"\\s+"}, -1},
std::sregex_token_iterator{},
[&](std::ssub_match sm) {
cmd.push_back(sm.str());
});
这是因为匿名std::regex
的生命周期与匿名std::sregex_token_iterator
对象相同。