我遇到了一些误导性问题。我有一个将字符串作为引用的函数,使用正则表达式将其拆分,将一部分保存回给定字符串并返回另一部分。但是,将一个匹配项分配给引用参数似乎会使匹配对象无效(看起来像是一种误用的移动分配),而将其分配给局部变量则可以正常工作。这是代码:
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 = "foo <- 5+5+5+5"):
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 都可以。
这是怎么回事?
最佳答案
std::smatch
对象是 std::match_results
模板的实例化。它在 cppreference 上的条目包含以下段落:
This is a specialized allocator-aware container. It can only be default created, obtained from std::regex_iterator, or modified by std::regex_search or std::regex_match. Because std::match_results holds std::sub_matches, each of which is a pair of iterators into the original character sequence that was matched, it's undefined behavior to examine std::match_results if the original character sequence was destroyed or iterators to it were invalidated for other reasons.
因为修改原始字符串(这是您通过分配给 szExp
所做的事情)会使迭代器在其字符序列中无效,所以您违反了上述规定并导致未定义的行为。
关于c++ - 分配给引用参数会使对象无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40550240/