当场对象创建与变量声明

开心果

我有以下代码(将字符串拆分为向量),使我在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());
});

谁能向我解释一下?

杰弗里·托马斯(Jeffery Thomas)

我知道答案,但我不喜欢它。我认为这可能是clang的缺陷。

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_);
}

这将__reas的地址存储在指针中。一旦__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对象的生存期与匿名对象相同

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

Related 相关文章

热门标签

归档