我有一个结构,其中包含对 vector 的引用。
然后,我创建此结构的 vector 。
我在此 vector 中创建此结构的三个三个实例。
然后,我擦除 vector 中该结构的第二个实例。
显然,这导致testData2的内容变得与testData3 !?的内容相同。
如何阻止这种情况的发生?我应该在结构的析构函数中添加一些东西来阻止这种情况发生吗?
还是我在这里做的事情很糟糕?如果是这样,为什么?
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
struct TESTSTRUCT
{
int &testInt;
std::vector<int> &testVector;
TESTSTRUCT(int &testIntInput, std::vector<int> &testVectorInput)
:testInt(testIntInput), testVector(testVectorInput) {}
TESTSTRUCT(const TESTSTRUCT &source)
:testInt(source.testInt), testVector(source.testVector) {}
TESTSTRUCT &operator=(const TESTSTRUCT &source)
{
testInt = source.testInt;
testVector = source.testVector;
return *this;
}
virtual ~TESTSTRUCT(){}
};
int main()
{
std::vector<int> testData1;
std::vector<int> testData2;
std::vector<int> testData3;
int a = 1;
int b = 2;
int c = 3;
testData1.push_back(10);
testData1.push_back(20);
testData1.push_back(30);
testData2.push_back(40);
testData2.push_back(50);
testData2.push_back(60);
testData3.push_back(70);
testData3.push_back(80);
testData3.push_back(90);
std::vector<TESTSTRUCT> *structVector = new std::vector<TESTSTRUCT>();
structVector->push_back(TESTSTRUCT(a, testData1));
structVector->push_back(TESTSTRUCT(b, testData2));
structVector->push_back(TESTSTRUCT(c, testData3));
std::cout<<&testData1[0]<<std::endl;
std::cout<<&testData2[0]<<std::endl;
std::cout<<&testData3[0]<<std::endl;
std::cout<<testData1[0]<<std::endl;
std::cout<<testData2[0]<<std::endl;
std::cout<<testData3[0]<<std::endl;
structVector->erase(structVector->begin()+1);
std::cout<<testData1[0]<<std::endl;
std::cout<<testData2[0]<<std::endl;
std::cout<<testData3[0]<<std::endl;
std::cout<<&testData1[0]<<std::endl;
std::cout<<&testData2[0]<<std::endl;
std::cout<<&testData3[0]<<std::endl;
return 0;
}
输出:
00711220
00711258
00717C68
10
40
70
10
70
70
00711220
00711258
00717C68
Press any key to continue . . .
编辑:
这是一个较大程序的示例。结构的实例用于我要渲染器绘制的东西,这些东西可以改变它们的位置(因此可以改变渲染器的绘制位置)。
最佳答案
该问题不是立即可见的。看一看TESTSTRUCT
的相等运算符:
TESTSTRUCT &operator=(const TESTSTRUCT &source)
{
testInt = source.testInt;
testVector = source.testVector;
return *this;
}
testVector
中的this
将获得source.testVector
的副本。现在,
structVector
中的main
包含三个TESTSTRUCT
实例,每个实例都通过引用绑定(bind)到自己的std::vector<int>
。当您调用structVector->erase(structVector->begin()+1);
时,TESTSTRUCT(b, testData2)
从structVector
中删除。erase
的规范指出,在请求的擦除位置之后,所有 vector 元素都向下移动(根据位置),以便使 vector 与内存相邻。我不知道该标准是否指定了有关在复制时需要如何实现erase
的任何内容,但是在我的实现(g++)中,调用了operator=
。这意味着,通过迭代器TESTSTRUCT
(实际上是structVector->begin()+1
)引用的structVector[1]
实例中通过引用存储的 vector 将获取structVector[2]
的内容。并且因为它是引用,所以它与testData2
中的main
本质上是相同的,这解释了为什么其内容与testData3
完全相同。但是,正如您所见,这是有效的,在调试时避免使用此类代码是有意义的。
关于c++ - 在不影响原始变量的情况下删除对变量的引用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23723965/