通过移动语义

时间:2016-02-17 16:42:12

标签: c++ iterator move-semantics

我有以下不可变容器类(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中遇到运行时错误。

在调试模式下,错误是:“list iterator not incrementable”。在for (int value : currentContainer->values)的第一次迭代之后发生此错误(当迭代器要递增时)。

在发布模式下,错误为:“位置0x38处的访问冲突读取”。此错误发生在copy.values.erase(value)的{​​{1}}。但只在第二次迭代中。令人惊讶的是,RemoveValue此时不再包含元素(values返回0)。

我不明白这些错误。我该如何解决?

A C++ Shell example也可以正常运行。但是,它会输出size()作为最终容器数,而我预计会有三个(最初的一个,一个删除了2,一个删除了1

1 个答案:

答案 0 :(得分:2)

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

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