我在Visual Studio 2013上,我看到了我认为的错误,我希望有人可以确认?
string foo{ "A\nB\rC\n\r" };
vector<string> bar;
for (sregex_iterator i(foo.cbegin(), foo.cend(), regex("(.*)[\n\r]{1,2}")); i != sregex_iterator(); ++i){
bar.push_back(i->operator[](1).str());
}
此代码命中Visual Studio regex库中的Debug Assertion:
regex_iterator
孤儿
如果我在regex
之外定义for
- 循环就可以了:
string foo{ "A\nB\rC\n\r" };
vector<string> bar;
regex bug("(.*)[\n\r]{1,2}");
for (sregex_iterator i(foo.cbegin(), foo.cend(), bug); i != sregex_iterator(); ++i){
bar.push_back(i->operator[](1).str());
}
或者,这可以在变换中正常工作,如this question:
所示string foo{ "A\nB\rC\n\r" };
vector<string> bar;
// This puts {"A", "B", "C"} into bar
transform(sregex_iterator(foo.cbegin(), foo.cend(), regex("(.*)[\n\r]{1,2}")), sregex_iterator(), back_inserter(bar), [](const smatch& i){ return i[1].str(); });
有人可以确认这是一个错误吗?
答案 0 :(得分:10)
在C ++ 11中,您可以将临时regex
绑定到const regex &
,如果迭代器在临时生命周期之外使用,则会导致未定义的行为,因为它将存储指针它。这是规范中的一个缺陷,虽然Visual Studio使用调试断言来捕获它,但它并不是错误。
sregex_iterator i(foo.cbegin(), foo.cend(), regex("(.*)[\n\r]{1,2}"))
^^^^^
temporary
以下已删除的重载是在{+ 3}}中添加C ++ 14以防止出现这种情况:
regex_iterator(BidirIt, BidirIt,
const regex_type&&,
std::regex_constants::match_flag_type =
std::regex_constants::match_default) = delete; (since C++14)
它说:
不允许使用临时正则表达式调用重载2, 因为返回的迭代器会立即失效。
因此,这不是Visual Studio
错误,因为它正在实施C ++ 11标准,直到后来才通过缺陷报告解决。使用clang
或更高版本的gcc
和-std=c++14
都会产生第一个错误( cppreference )和第三个错误( {{3 }} )示例。 Visual Studio仅开始支持see it live中的某些C ++ 14:
[...]以及对某些C ++ 14功能的初始支持。[...]
我们可以看到see it live处理此问题:
用户可以写“for(sregex_iterator i(s.begin(),s.end(), 正则表达式(“喵”)),结束;我!=结束; ++ i)“,将临时正则表达式绑定到 const regex&amp;并存储指向它的指针。这将静默编译, 在运行时触发未定义的行为。我们现在拥有这项技术 防止这种情况编译,就像reference_wrapper拒绝一样 绑定到临时工。
作为T.C.指出你显示的最后一个例子实际上是好的,即使你绑定了一个临时的,它的生命周期延伸到了表达式的结尾。
答案 1 :(得分:2)
不,这不是错误。见LWG 2329 regex_match()/regex_search() with match_results should forbid temporary strings。此构造表现出未定义的行为,因为它将临时正则表达式绑定到const正则表达式&amp;并存储指向它的指针。
另请参阅C++14 STL Features, Fixes, And Breaking Changes In Visual Studio 14 CTP1,其中列出了此修复程序。