我遇到了一些误导性的问题。我有一个函数,它将字符串作为引用,使用正则表达式将其拆分,将一部分保存回给定字符串并返回另一部分。但是,为引用参数分配一个匹配似乎使匹配对象无效(看起来像是一种误用的移动赋值),而将其分配给局部变量则可以正常工作。这是代码:
std::string ParseVar(std::string & szExp)
{
static std::regex oRegex("^([[:alpha:]][[:alnum:]_]*)\\s*<-\\s*(.+)$");
std::smatch oMatch;
if (std::regex_match(szExp, oMatch, oRegex))
{
if (oMatch.size() != 3)
throw std::runtime_error("internal error");
std::cout << "Match before: " << oMatch.str(2) << std::endl;
szExp = oMatch.str(2);
std::cout << "Match after: " << oMatch.str(2) << std::endl;
return oMatch.str(1);
}
return "";
}
打印(对于szExp =&#34; foo&lt; - 5 + 5 + 5 + 5&#34;):
Match before: 5+5+5+5
Match after: +5+5+5
返回的值似乎也被打破了,但是szExp包含正确的字符串。
将其更改为:
std::string ParseVar(std::string & szExp)
{
static std::regex oRegex("^([[:alpha:]][[:alnum:]_]*)\\s*<-\\s*(.+)$");
std::smatch oMatch;
std::string save1, save2;
if (std::regex_match(szExp, oMatch, oRegex))
{
if (oMatch.size() != 3)
throw std::runtime_error("internal error");
save1 = oMatch.str(1);
save2 = oMatch.str(2);
std::cout << "Match before: " << oMatch.str(2) << std::endl;
szExp = save2;
std::cout << "Match after: " << oMatch.str(2) << std::endl;
return save1;
}
return "";
}
打印相同的东西,但至少两个返回值和szExp都没问题。
这里发生了什么?
答案 0 :(得分:1)
std::smatch
对象是std::match_results
模板的实例化。它在cppreference上的条目包含以下段落:
这是一个专门的分配器感知容器。它只能是 默认创建,从std :: regex_iterator获取,或由。修改 std :: regex_search或std :: regex_match。因为std :: match_results 持有std :: sub_matches,每个都是一对迭代器 匹配的原始字符序列,它的未定义行为 如果原始字符序列是,则检查std :: match_results 由于其他原因,销毁或其迭代器无效。
因为修改原始字符串(这是你通过分配给szExp
所做的事情)使迭代器无效到它的字符序列中,你就会犯下上述行为并导致未定义的行为。