2016-02-17 98 views
1

我有以下的不可變的容器類(以values公共訪問只是爲了簡單的原因)無效設置迭代器:通過移動語義

struct Container 
{ 
    std::unordered_set<int> values; 

    //Default constructor 
    Container() = default; 

    //Copy constructor 
    Container(const Container& other) 
     : values(other.values) 
    { } 

    //Move constructor 
    Container(const Container&& other) 
     : values(std::move(other.values)) 
    { } 

    Container RemoveValue(int value) const 
    { 
     //Create a copy of this object 
     Container copy(*this); 
     //Remove one element from the copy 
     copy.values.erase(value); 
     return copy; 
    } 
}; 

該容器中含有一組值。方法RemoveValue()返回已刪除特定值的當前對象的副本。爲此結構定義了適當的移動構造函數。

我使用此容器如下:

int main() 
{ 
    std::vector<Container> containers; 

    { 
     //Initialization 
     Container initialContainer; 
     initialContainer.values.insert(1); 
     initialContainer.values.insert(2); 

     containers.push_back(std::move(initialContainer)); 
    } 

    const Container* currentContainer = &containers.front(); 
    for (int value : currentContainer->values) 
    { 
     Container newContainer = currentContainer->RemoveValue(value); 

     //Do some checks, then... 
     containers.push_back(std::move(newContainer)); 
    } 

    std::cout << containers.size() << std::endl; 

    return 0; 
} 

我初始化容器的矢量與單個容器(具有值1和2)。然後,我獲得一個指向這個初始元素的指針並迭代每個值。對於每個值,我調用RemoveValue()並將生成的容器插入向量中。

在gcc中,這似乎工作得很好。但是,我在Visual Studio 2015中遇到運行時錯誤。

在調試模式下,錯誤是:「列表迭代器不可增量」。在for (int value : currentContainer->values)的第一次迭代之後發生此錯誤(迭代器要遞增時)。

在發佈模式下,錯誤是:「訪問衝突讀取在位置0x38」。此錯誤發生在copy.values.erase(value),RemoveValue。但僅在第二次迭代中。令人驚訝的是,values此時不包含元素(size()返回0)。

我不明白這些錯誤。我該如何解決它們?

A C++ Shell example也運行沒有錯誤。然而,它輸出2作爲集裝箱的最終數量,而我預期三個(最初的一個,一個去掉1,一個去掉2)。

回答

2

currentContainer是指向矢量containers的元素的指針。循環體通過調用push_back來修改containers。這可以使指向矢量的指針無效,如果是這樣,currentContainer最終可能指向垃圾。

通常,不要使用指向std::vector中保存的對象的指針。相反,請使用containers.front()containers[0]來獲取第一個元素。