设置因移动语义而无效的迭代器
Set iterator invalidated by move semantic
我有以下不可变容器 class(public 访问 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()
returns 已删除特定值的当前对象的副本。为此结构定义了适当的移动构造函数。
我使用这个容器如下:
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)
的第一次迭代之后(当迭代器要递增时)。
在发布模式下,错误是:"Access violation reading at position 0x38"。此错误发生在 RemoveValue
中的 copy.values.erase(value)
。但仅限于第二次迭代。令人惊讶的是,values
此时不再包含元素 (size()
returns 0).
我不明白这些错误中的任何一个。我该如何解决它们?
A C++ Shell example 也可以正常运行。但是,它输出 2
作为容器的最终数量,而我预期是三个(第一个,一个删除了 1
,一个删除了 2
)。
currentContainer
是指向向量 containers
的元素的指针。循环体通过调用push_back
修改containers
。这会使指向向量的指针无效,如果确实如此,currentContainer
可能最终指向垃圾。
一般来说,不要使用指向 std::vector
中保存的对象的指针。相反,使用 containers.front()
或 containers[0]
获取第一个元素。
我有以下不可变容器 class(public 访问 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()
returns 已删除特定值的当前对象的副本。为此结构定义了适当的移动构造函数。
我使用这个容器如下:
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)
的第一次迭代之后(当迭代器要递增时)。
在发布模式下,错误是:"Access violation reading at position 0x38"。此错误发生在 RemoveValue
中的 copy.values.erase(value)
。但仅限于第二次迭代。令人惊讶的是,values
此时不再包含元素 (size()
returns 0).
我不明白这些错误中的任何一个。我该如何解决它们?
A C++ Shell example 也可以正常运行。但是,它输出 2
作为容器的最终数量,而我预期是三个(第一个,一个删除了 1
,一个删除了 2
)。
currentContainer
是指向向量 containers
的元素的指针。循环体通过调用push_back
修改containers
。这会使指向向量的指针无效,如果确实如此,currentContainer
可能最终指向垃圾。
一般来说,不要使用指向 std::vector
中保存的对象的指针。相反,使用 containers.front()
或 containers[0]
获取第一个元素。