2016-11-11 77 views
1

我遇到了一些誤導性問題。我有一個函數,它將字符串作爲參考,使用正則表達式分割它,將一個部分保存回給定的字符串並返回另一個。然而,將一個匹配分配給引用參數似乎會使匹配對象無效(看起來像是一種錯誤的移動賦值),而將其分配給局部變量則可以正常工作。下面的代碼:分配參考參數使對象無效

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 = 「富< - 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的罰款。

這是怎麼回事嗎?

回答

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做什麼)無效迭代器的字符序列,你屬於以上並造成未定義行爲的犯規。

+0

@PKua是將字符串複製到保存變量確實使完全獨立的副本。然而,它不是你要輸出的那些副本 - 而是你再次調用oMatch.str()(在你的'std :: cout'行) – Smeeheey

+0

需要記住的是oMatch依然依賴於' szExp'的整個生命週期。任何對'oMatch.str()'的調用都會產生一個獨立的字符串,但後來的重複調用仍然需要'szExp'不會失效 – Smeeheey

+0

我注意到szExp是我的原始字符串,因此在發佈評論後修改它會使迭代器失效,所以我刪除了它(因爲問題在你回答後實際上很愚蠢)。 對於那些將來會閱讀它的人來說:評論中的問題是「do'oMatch.str()'創建原始字符串的尖頭部分的副本嗎?」。 無論如何,現在我可以(希望)瞭解一切。非常感謝。 – PKua