2016-03-31 76 views
0

我創建了這個函數,它可以處理矢量,鏈表和雙鏈表。該函數獲取一個值並在容器中搜索它。如果vlaue位於容器中,則該函數將在已存在的位置旁邊插入值。所以,如果val=2那麼{3,2,5}將變成{3,2,2,5}。但是,如果該容器中不存在該值,則會將其添加到後面。EXC與迭代器訪問錯誤

我用迭代器編寫了這個函數。它適用於矢量,但是當我嘗試使用列表或雙鏈表來運行它時,我會在行if (*it==val)處發生Exc Bad Access錯誤。我沒有看到我做錯了什麼。

template <class Container, class T> 
void insertNextTo(Container &x, const T &val){ 
    typename Container::iterator it = x.begin(); 
    while (it!=x.end() && *it!=val){ 
     ++it; 
    } 
    if (*it == val){ 
     x.insert(it, val); 
    } 
    else{ 
     x.push_back(val); 
    } 
} 

編輯:謝謝大家!您的建議更改if聲明完美無缺!

+0

如果沒有找到'val',那麼'if'條件推斷導致UB的結束元素。 – Mahesh

回答

2

變化

if (*it == val) 

到:

if (it != x.end()) 

如果在容器中找不到val,則循環將在時結束。這指向數組的末尾,因此通過它導致未定義的行爲。

0

有人糾正我,如果我錯了,但我相信你的錯誤來自於這樣當你的迭代器到達列表的末尾,它實際上列表在內存中,最後位後指向地址中的事實,可能會或可能不會被初始化,並在範圍內,這會導致您的程序出錯。

2

如果該值不存在,則在循環結束時it將等於end(),並且不能取消end()。您需要更改if (*it == val)if (it != x.end())代替:

//if (*it == val){ 
if (it != x.end()){ 
    x.insert(it, val); 
} 

或者,因爲你只插入一個值,如果你發現val那麼你可以做的insert()並立即退出該功能,然後push_back()只有當循環到達容器的端部:

template <class Container, class T> 
void insertNextTo(Container &x, const T &val) { 
    typename Container::iterator it = x.begin(); 
    while (it != x.end()) { 
     if (*it == val) { 
      x.insert(it, val); 
      return; 
     } 
     ++it; 
    } 
    x.push_back(val); 
} 

在這種情況下,可以通過使用std::find()代替手動迴路簡化代碼:

#include <algorithm> 

template <class Container, class T> 
void insertNextTo(Container &x, const T &val) { 
    typename Container::iterator it = std::find(x.begin(), x.end(), val); 
    if (it != x.end()) { 
     x.insert(it, val); 
    } else { 
     x.push_back(val); 
    } 
} 

甚至這一點,因爲它是使用end()迭代安全insert(),它是有效的一樣push_back()

template <class Container, class T> 
void insertNextTo(Container &x, const T &val) { 
    typename Container::iterator it = std::find(x.begin(), x.end(), val); 
    x.insert(it, val); 
}