分配给引用参数会使对象无效

时间:2016-11-11 14:36:26

标签: c++ c++11 reference

我遇到了一些误导性的问题。我有一个函数,它将字符串作为引用,使用正则表达式将其拆分,将一部分保存回给定字符串并返回另一部分。但是,为引用参数分配一个匹配似乎使匹配对象无效(看起来像是一种误用的移动赋值),而将其分配给局部变量则可以正常工作。这是代码:

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都没问题。

这里发生了什么?

1 个答案:

答案 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所做的事情)使迭代器无效到它的字符序列中,你就会犯下上述行为并导致未定义的行为。