自定义对象压入vector时候的问题

lasvegas_xiang 2011-09-21 09:14:11
class HuffmanNode
{
private:
int weight;//权值
char data;//对应的字符
public:
HuffmanNode* left;
HuffmanNode* right;
bool visit;
string code;//编码
HuffmanNode():weight(0),data(' '),left(NULL),right(NULL),
visit(false),code(""){}
HuffmanNode( const HuffmanNode& node);
~HuffmanNode()
{

}
HuffmanNode& operator= (const HuffmanNode& right);
bool SetWeight(int w);
int GetWeight() const;
bool SetData(char ch);
char GetData();
};

以上是HuffmanNode这个类的定义,以下是HuffmanTree的定义:
class HuffmanTree
{
private:
HuffmanNode* root;
vector<HuffmanNode> allNode;
HuffmanNode* FindMin();
int GetUnVisitCount();
HuffmanNode* GetUnVisitNode();
public:
HuffmanTree():root(NULL)
{
allNode.reserve(100);
}
bool Create();
bool SetAllNode(vector<HuffmanNode> node);
void GetAllHuffmanCode(HuffmanNode* t);
HuffmanNode* GetRoot() const;
void OutputAllCode();
};
在HuffmanTree的Create函数里面往allNode里push_back出错!
HuffmanNode* minnode1 = FindMin();
HuffmanNode* minnode2 = FindMin();
HuffmanNode newNode;
int newWeight = minnode1->GetWeight() + minnode2->GetWeight();
newNode.SetWeight(newWeight);
newNode.left = minnode1;
newNode.right = minnode2;
allNode.push_back(newNode);
调试的时候发现newNode赋值完全正确,但是在push_back之后,allNode里本应该出现newNode的副本,但是这个副本的left和right却和newNode不一样
后来google翻了几页终于找到解决方法了(http://blog.sina.com.cn/s/blog_4b9cc6db0100cbw3.html),在HuffmanTree的构造函数里面allNode.reserve(100)分配一下空间就行了,我想问这是为什么呢 为什么reserve一下就正确了,push_back空间不足的话vector应该会自己重新申请空间吧?
...全文
201 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
zxzxghgh 2011-09-22
  • 打赏
  • 举报
回复
vector是动态申请
dahaiI0 2011-09-22
  • 打赏
  • 举报
回复
应该是这样的。如果结点new出来再push进去,重新分配时拷贝的是你new出来结点的地址,所有结点的地址都不会变,每个结点的left-right自然不会变,你可以自己再验证下
lasvegas_xiang 2011-09-22
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 dahaii0 的回复:]

假设有2个结点,第一个结点地址为0x1001,第二个0x1002,第一个结点的left=0x1002(假设),如果此时插入第三个发现空间不足要重新分配,先把2个结点的数据拷贝进新分配的内存,然后删除当前的,你认为第二个结点的地址还是0x1002么。
[/Quote]
我突然明白了,将情况简化如下我的vector里有三个变量,假设是 node0,node1,node2 在内存中中地址假设为:0x0000,0x0001,0x0002
node0的两个指针成员分别指向node1和node2 也就是:两个指针值为0x0001,0x0002
此时如果我再push_back进一个元素,而且此时vector空间不足了,需要自己重新再内存中另外找一块连续的空间,假设连续空间为0x0010~0x0013 那么由于我实现的HuffmanNode的拷贝函数是将两个指针成员的值复制,所以此时node0的两个指针成员还是指向0x0001,0x0002
所以会出错,但是此时正确的应该是指向0x0011,0x0012

为什么提前reserve就没问题呢,因为这样就避免了重新在内存中寻找连续空间,对原有vector进行拷贝构造,指针的值就不会失效!

不知道我说得对不
pengzhixi 2011-09-22
  • 打赏
  • 举报
回复
reserve解决不了根本问题,reserve只是说会保留相对多点的预留空间为以后push_back进来的元素。但是一旦预留空间用完(或者接近用完)照样会引起空间的重新申请分配,星羽建议存放指针,减少push_back对象引起的不必要的拷贝构造函数的调用从而降低效率,而且vector本身内部分配的内存也不用那么大。唯一需要做的是你要自己为对象new然后delete自己接管对象生存。
dahaiI0 2011-09-22
  • 打赏
  • 举报
回复
假设有2个结点,第一个结点地址为0x1001,第二个0x1002,第一个结点的left=0x1002(假设),如果此时插入第三个发现空间不足要重新分配,先把2个结点的数据拷贝进新分配的内存,然后删除当前的,你认为第二个结点的地址还是0x1002么。
AndyZhang 2011-09-22
  • 打赏
  • 举报
回复
vector是动态申请,除非你内存没有空间了才会失败
lasvegas_xiang 2011-09-22
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 dahaii0 的回复:]

前几天稍微看了下vector,内部有个变量标识了当前最大容量,当push_back一个数据,如果满了,则重新分配当前空间的1.5倍大小,并把当前保存的数据复制过去,让后delete当前分配的内容。reserve之后就没出问题了,这个reserve就是调整最大容量的,设置100后只要当前数据没超过这么多久不会重新分配,超过了就会再次分配150的大小,你的vector中保存的是对象,重新分配内存时把……
[/Quote]
当vector空间不足的时候 它应该自己会重新分配空间吧 reserve的必要性在这里有没有,为什么要reserve
chiyer说的很有道理,但为什么不reserve就失效呢,vector空间不足? 不足的话不会自己重新分配吗
dahaiI0 2011-09-21
  • 打赏
  • 举报
回复
前几天稍微看了下vector,内部有个变量标识了当前最大容量,当push_back一个数据,如果满了,则重新分配当前空间的1.5倍大小,并把当前保存的数据复制过去,让后delete当前分配的内容。reserve之后就没出问题了,这个reserve就是调整最大容量的,设置100后只要当前数据没超过这么多久不会重新分配,超过了就会再次分配150的大小,你的vector中保存的是对象,重新分配内存时把数据(结点)拷贝过去,此时重新分配的内存地址肯定跟上次的不一样,每个结点的内存地址都会变化,所以这个副本的left和right却和newNode不一样 ,不知道我说的对不对,树的相关知识都忘光了,说错了楼下不吝纠正
星羽 2011-09-21
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 kk791159796 的回复:]

引用 2 楼 chiyer 的回复:

push HuffmanNode* 吧

给个理由吧 为什么不用HuffmanNode 而要用指针
[/Quote]


1. 当你的HuffmanNode 结构很大,比 void* 大的时候,vector的拷贝构造开销是很客观的
2.用指针,就不会出现你上面的问题, vector的充分配空间不会造成你的结构中的next prev无效

lasvegas_xiang 2011-09-21
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 chiyer 的回复:]

push HuffmanNode* 吧
[/Quote]
给个理由吧 为什么不用HuffmanNode 而要用指针
lasvegas_xiang 2011-09-21
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 mstlq 的回复:]

是呀,会重新申请,所以以前指向那些节点的指针都失效了呀……

楼主你加了allNode.reserve(100)的话,push_back100来个节点后,照样挂的
[/Quote]
reserve之后就没出问题了 一切正常啊
hui12345685 2011-09-21
  • 打赏
  • 举报
回复
这个你要问编译器的实现,如果担心出现这种问题,可以像楼上说的vector里面存指针,然后在析构函数中自己释放内存。
星羽 2011-09-21
  • 打赏
  • 举报
回复
HuffmanNode 都new 出来,push 进去指针,自己管理释放
星羽 2011-09-21
  • 打赏
  • 举报
回复
push HuffmanNode* 吧
mstlq 2011-09-21
  • 打赏
  • 举报
回复
是呀,会重新申请,所以以前指向那些节点的指针都失效了呀……

楼主你加了allNode.reserve(100)的话,push_back100来个节点后,照样挂的

64,642

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧