C++ 当场创建对象与变量声明

C++ 当场创建对象与变量声明,c++,c++11,C++,C++11,我有以下代码(将字符串拆分为向量),在for_each循环的第二次迭代中提供segfault: 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_eac

我有以下代码(将字符串拆分为向量),在for_each循环的第二次迭代中提供segfault:

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

有人能给我解释一下吗?

我知道答案,但我不喜欢。我认为这可能是叮当声的一个缺陷

std::sregex\u token\u迭代器正在保存指向正则表达式的指针

在第一个版本中,匿名
std::regex
对象在构造
splitter
后被销毁。这将使拆分器指向内存中释放的空间

在第二个版本中,
rx
将一直有效,直到块结束。这使得拆分器指向正确的对象


std::regex\u token\u迭代器
constructor

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);
}
这将
\uu re
的地址存储为指针。一旦
\uuuu re
超出范围,
\uuu re
将被销毁
\uuuu位置
留下一个悬空指针


最后一个音符

以下工作:

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\u token\u迭代器对象的生命周期相同。

我知道答案,但我不喜欢它。我认为这可能是叮当声的一个缺陷

std::sregex\u token\u迭代器正在保存指向正则表达式的指针

在第一个版本中,匿名
std::regex
对象在构造
splitter
后被销毁。这将使拆分器指向内存中释放的空间

在第二个版本中,
rx
将一直有效,直到块结束。这使得拆分器指向正确的对象


std::regex\u token\u迭代器
constructor

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);
}
这将
\uu re
的地址存储为指针。一旦
\uuuu re
超出范围,
\uuu re
将被销毁
\uuuu位置
留下一个悬空指针


最后一个音符

以下工作:

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\u token\u迭代器对象的生存期相同。

可以使用
std::stringstream
轻松拆分字符串(如果分隔符是空格)。请参阅。构造函数获取对正则表达式的常量引用。那太糟糕了。我认为他们应该添加一个带有右值引用的已删除重载。不确定第一个版本是如何通过编译的。应该使用新的吗?你的编译器的版本是什么?4.9.0之前的GCC在std::regex'sHas中失败,这是不是用CLang++(例如3.3或更新版本)尝试过?我很想知道CLang是否为这两个版本正确编译了
std::regex
。您可以使用
std::stringstream
轻松拆分字符串(如果分隔符是空格)。请参阅。构造函数获取对正则表达式的常量引用。那太糟糕了。我认为他们应该添加一个带有右值引用的已删除重载。不确定第一个版本是如何通过编译的。应该使用新的吗?你的编译器的版本是什么?4.9.0之前的GCC在std::regex'sHas中失败,这是不是用CLang++(例如3.3或更新版本)尝试过?我很想知道CLang是否为这两个版本正确编译了
std::regex