2015-06-24 70 views
2

我試圖從正則表達式匹配到filesystem::path對象列表中分析出文件名。std :: transform中的分割錯誤

我相信匹配是有效的,因爲for_each爲相同的迭代器和打印控制檯完美工作。但是,我收到運行此代碼的分段錯誤。我究竟做錯了什麼?我的lambda中有錯誤嗎?

 namespace fs = boost::filesystem; 
     std::forward_list<fs::path> results; 
     std::transform(std::sregex_iterator(file_data.begin(), file_data.end(), re), 
         std::sregex_iterator(), results.begin(), 
         [&](const std::smatch& m)->fs::path{ 
      return root/fs::path(m[1].str()); 
     }); 

GDB表明我這條線作爲一個地方的錯誤:

path& operator=(const path& p) 
{ 
    m_pathname = p.m_pathname; 
    return *this; 
} 

UPDATE:找到了解決辦法 - 使用back_inserter(results)代替results.begin()。但是,爲什麼呢?

+0

您確定您使用過'back_inserter',而不是'front_inserter'嗎? 'forward_list'沒有'push_back'函數,所以'back_inserter'不應該與它一起工作。 –

回答

3

std::transform算法的第三個參數應該是應寫入值的範圍的開始的迭代器。具體來說,它通過覆蓋迭代器指向的範圍內的值和變換後的值來工作。這意味着實際上必須有值才能重寫。在你的情況下,你寫入一個空的forward_list,所以沒有什麼可寫的,因此崩潰。

爲了解決這個問題,可以考慮用back_inserter替換最後一個參數,它會自動打造了所需的值所產生的空間:

std::transform(std::sregex_iterator(file_data.begin(), file_data.end(), re), 
       std::sregex_iterator(), 
       back_inserter(results), // <--- This is new 
       [&](const std::smatch& m)->fs::path{ 
     return root/fs::path(m[1].str()); 
}); 

更普遍,據我所知,所有的寫入到輸出範圍的<algorithm>中的算法將假定在該範圍內有可覆蓋的值。如果不是這種情況,請考慮使用back_inserter或其他類型的插入迭代器,它將自動創建您需要的空間。

希望這會有所幫助!

2

輸出迭代器是一個簡單的results.begin(),可能是== results.end()。這裏的線索是試圖分配結果時出現故障。

您或者需要找到back_inserter,或者使用一些容器已經分配了足夠的空間(只有在知道您需要提前轉換多少物品的情況下才能使用)。

具體而言,請考慮第一個過載here的樣本實施。

*d_first++ = op(*first1++); 

需要目標迭代器已經是有效的。如果建議爲== end(),則整個操作是非法的。

+0

明白了。謝謝 – amigo421