设置迭代器因移动语义失效

Set iterator invalidated by move semantic

本文关键字:语义 失效 移动 迭代器 设置      更新时间:2023-10-16

我有以下不可变的容器类(公共访问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 处访问违规读取"。此错误发生在 RemoveValue 中的 copy.values.erase(value) 处。但仅限于第二次迭代。令人惊讶的是,此时values不再包含元素(size()返回 0(。

我不明白这些错误中的任何一个。如何解决这些问题?

C++命令行管理程序示例也运行时没有错误。但是,它输出2作为最终数量的容器,而我预计有三个(初始容器,一个删除了1,一个删除了2(。

currentContainer 是指向向量containers元素的指针。循环体通过调用push_back来修改containers。这可能会使指向矢量的指针无效,如果是这样,currentContainer最终可能会指向垃圾。

通常,不要使用指向std::vector中保存的对象的指针。相反,请使用containers.front()containers[0]来获取第一个元素。