我有一个结构,其中包含对 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/

10-09 09:00