删除对变量的引用而不影响原始变量

时间:2014-05-18 16:03:12

标签: c++ vector struct reference

我有一个包含对向量引用的结构。

然后我创建了这个结构的向量。

我在这个向量中创建了这个结构的三个三个实例。

然后我在向量中擦除结构的第二个实例。

这显然导致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 . . .

编辑:

这是一个较大程序的例子。结构的实例是我希望渲染器绘制的东西,这些东西可以改变它们的位置(因此渲染器应该绘制它们的位置)。

2 个答案:

答案 0 :(得分:0)

问题无法立即显现。看看TESTSTRUCT

的等于运算符
TESTSTRUCT &operator=(const TESTSTRUCT &source)
{
    testInt = source.testInt;
    testVector = source.testVector;

    return *this;
}

testVector中的this将获得source.testVector的副本。

现在,structVector中的main包含三个TESTSTRUCT个实例,每个实例都通过引用绑定到自己的std::vector<int>。当您致电structVector->erase(structVector->begin()+1);时,TESTSTRUCT(b, testData2)已移除structVector

erase的规范表示在请求的擦除位置之后的所有向量元素向下移位(就位置而言),以便向量是存储器连续的。我不知道标准是否指定了在复制时需要实现erase的方式,但在我的实现(g ++)中,调用了operator=。这意味着通过引用在迭代器TESTSTRUCT引用的structVector->begin()+1实例中存储的向量(实际上,structVector[1])获取structVector[2]的内容。因为它是一个参考,它与testData2中的main基本相同,这解释了为什么它的内容与testData3完全相同。

然而,这是有效的,因为您可以看到自己,在调试时避免使用这些代码。

答案 1 :(得分:0)

你过度使用引用(有点不正确)。您的TESTSTRUCT个对象包含对testdata1testdata2testdata3的引用。因此,当您修改structVector时,前两个向量也会被修改。因此,当您从structVector中删除第二个元素时,第三个元素会占据它的位置。因此,内部元素(即testdata2)也会替换为main中的testdata3,因为它们的引用包含在struct中。