性病::矢量擦除()问题 [英] std::vector erase() problem

查看:124
本文介绍了性病::矢量擦除()问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我下面的代码将一个类的5个实例添加到向量中,然后使用delete()删除向量的第一项. delete()确实删除了第一项.但是它删除了第五个!
在Visual Studio和Xcode/GCC中进行了尝试.我做错了什么?

谢谢,

托马斯

---代码:---

Hi,

my code below adds 5 instances of a class to a vector and then uses erase() to remove the vector''s first item. erase() really removes the first item. But it deletes the 5th!
Tried it in Visual Studio and Xcode/GCC. What am I doing wrong?

Thanks,

Thomas

--- code: ---

#include "stdafx.h"
#include <vector>

bool bVectorErase = false;

class c
{
public:
	c()
	{
		pStr = 0;
	}
	~c()
	{
		if(pStr)
			delete pStr;
	}
	//copy constructor:
	c(const c & other)
	{
		pStr = 0;
		SetI(other.i);
	}
	//in will be passed to the struct''s int and string
	void SetI(int in)
	{		
		i = in;
		if(pStr)
			delete pStr;
		pStr = new char [10];
		sprintf(pStr, "%d", in);
	};
	int i;
	char * pStr;
};

void TestVectorErase()
{
	long ix;
	std::vector<c> vctc;
	for(ix = 0; ix < 5; ix ++)
	{
		c cinst;
		cinst.SetI(ix);
		vctc.push_back(cinst);
	}
	bVectorErase = true;
	char * pShouldBeDeleted = vctc[0].pStr;
	char * pShouldNotBeDeleted = vctc[4].pStr;
	vctc.erase(vctc.begin());
}

推荐答案

for(ix = 0; ix < 5; ix ++)
{
          c cinst;
          cinst.SetI(ix);
          vctc.push_back(cinst);
}



首先,首先要在您的for循环中创建该类对象的所有实例,并且在循环完成后它们将立即死亡.当然,您正在创建该类的5个实例,但是类对象(cinst)将完全不在for循环之外).在问其他任何问题之前,您需要先解决那个问题.如何将它们放到堆上并稍后delete?



First things first - all instances of the class object are being created within your for loop, and they will die IMMEDIATELY after the loop is done. Sure, you''re creating 5 instances of the class, but the class objects (cinst) will NOT exist outside the for loop at all). Before asking anything else, you need to take care of that. How about putting those on the heap and deleteing them later?


删除第一个项目时,此后的每个项目都将下移一个步骤.

因此,当您删除索引0时,以下索引会更改.

[0]->已删除
[1]-> [0]
[2]-> [1]
[3]-> [2]
[4]-> [3]

如您所见,[4]处的元素现在位于[3] ...

在幕后,所有的内存都被物理复制.

因此,您将获得实现这种效果的代码在后台运行.

vctc [0] = vctc [1];
vctc [1] = vctc [2];
vctc [2] = vctc [3];
vctc [3] = vctc [4];


因此,如果您有大型数组,则使用指向数组中对象的指针比对象本身更有效.

************************

正如我在上述解决方案中提到的那样,您需要进行深拷贝以避免重复删除.

将其放在您的类定义中.
When it deletes the first item, every item after that, then gets shifted down one step.

So when you erase index 0, the following indexes change.

[0] -> Erased
[1] -> [0]
[2] -> [1]
[3] -> [2]
[4] -> [3]

So as you can see, the element at [4] is now at [3]...

Behind the scenes, all of that memory is being physically copied.

So you''ll get code to this effect working behind the scenes.

vctc[0] = vctc[1];
vctc[1] = vctc[2];
vctc[2] = vctc[3];
vctc[3] = vctc[4];


So if you have large arrays, it''s more efficient to use pointers to your object in the array, than the objects themselves.

************************

As I mentioned in the above solution, you need a deep copy to avoid double deletes.

Put this in your class definition.
public:
    c(const c & rhs);



然后在您的.cpp



Then this in your .cpp

c::c(const c & rhs)
{
    pStr = 0;
    SetI(rhs.i);
}


这是您的问题:
This is your problem:
char * pShouldBeDeleted = vctc[0].pStr;
char * pShouldNotBeDeleted = vctc[4].pStr;
vctc.erase(vctc.begin());


调用erase()之后,向量中只有4个元素,因此指针pShouldNotBeDeleted不再有效,因为它指向不再存在的vctc [4](如Jack所述,它们都向上移动了一个).如果您使用调试器逐步执行代码,则可以更好地了解正在发生的事情.


Following the call to erase() you have only 4 elements in the vector so the pointer pShouldNotBeDeleted is no longer valid as it points to vctc[4] which no longer exists (as Jack mentioned, they have all moved up one). If you step through your code with the debugger you will get a better idea of what is happening.


这篇关于性病::矢量擦除()问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆