鱼C论坛

 找回密码
 立即注册
查看: 1866|回复: 9

[已解决]vector 出错 vector iterators incompatible

[复制链接]
发表于 2021-11-13 11:15:25 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 zy8818 于 2021-11-13 13:47 编辑

vector 出错
编译器提示
Expression:vector iterators incompatible
定义:
//多叉树结构
struct TreeNode
{
        CPoint pos;        //当前点
        vector<TreeNode*> childs;//子节点动态数组
        TreeNode*                pParent;//父节点

};

源码:
        vector<TreeNode*>::iterator it;
        TreeNode* pNew = new TreeNode;
        memset(pNew, 0, sizeof TreeNode);//把此行注释后while (it != pRoot->childs.end())可以用 但是链表的父节点不为空就做不了根节点,父节点循环失效
        //起点为根节点
        TreeNode* pRoot = pNew;
        //buff动态数组
        vector<TreeNode*>buff;
        //当前节点
        TreeNode* pCurrent = pRoot;
        TreeNode* pChild2 = new TreeNode;
        memset(pChild2, 0, sizeof TreeNode);
        TreeNode *pTemp = new TreeNode;
        memset(pTemp, 0, sizeof TreeNode);
        //加入pRoot成员childs vector
        pCurrent->childs.push_back(pChild2);
        pCurrent->childs.push_back(pTemp);
        //父节点指向pRoot
        pChild2->pParent = pRoot;
        pTemp->pParent = pRoot;

        //入buff vector
        buff.push_back(pChild2);
        buff.push_back(pTemp);

        it = pRoot->childs.begin();

        while (it != pRoot->childs.end())//出错断在此行
        {
                it++;
                AfxMessageBox(TEXT("|"));
        }

        it = buff.begin();
        while (it != buff.end())//下面的循环没有任何问题
        {
                it++;
                AfxMessageBox(TEXT("|"));
        }
最佳答案
2021-11-14 19:13:50
zy8818 发表于 2021-11-13 19:45
什么原理?我用debung调试模式看注释和不注释memset的情况下 pRoot->childs下面都有两个push进去的对象 ...

这个原理很复杂(我dubug了半天也没搞清楚),但你不需要知道
原因很简单:原理不具有可移植性。
具体点说,对vector这种不具有内存平凡型的类使用memset()这类字节操作是未定义行为,这之后的一切行为都由编译器实现决定。我用Mingw测试的时候push_back()没有问题,用iterator遍历也没有问题。但用VS2019测试时push_back()没有问题,用iterator遍历出了问题。
写C++一定要牢记一个原则:永远不要尝试未定义行为,更不要尝试探究未定义行为背后的原理,因为换一个编译器(甚至是升级一个版本),其原理就会发生改变。知道其中的工作原理不仅不会让你用起来得心应手,还会让你撞得头破血流。请相信我学C++这几年的经验下次离未定义行为越远越好
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-11-13 19:27:23 | 显示全部楼层

回帖奖励 +50 鱼币

好家伙,memset(pNew, 0, sizeof(TreeNode))直接把vector的内存置零了,不出bug才怪
直接pNew->pParent = 0;就行了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-13 19:45:36 | 显示全部楼层
本帖最后由 zy8818 于 2021-11-13 19:59 编辑
lhgzbxhz 发表于 2021-11-13 19:27
好家伙,memset(pNew, 0, sizeof(TreeNode))直接把vector的内存置零了,不出bug才怪
直接pNew->pParent =  ...


什么原理?我用debung调试模式看注释和不注释memset的情况下 pRoot->childs下面都有两个push进去的对象
001.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-13 22:09:44 | 显示全部楼层

回帖奖励 +50 鱼币

pNew->pParent = 0  我也跟着学习一下 混点鱼币
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-13 22:43:23 | 显示全部楼层
本帖最后由 zy8818 于 2021-11-14 10:17 编辑
zhsguitar 发表于 2021-11-13 22:09
pNew->pParent = 0  我也跟着学习一下 混点鱼币


真正的原理没有找到兄弟们,单条指令pNew->pParent = 0我也会,不然我怎么知道注释memset,我想知道的是后面的原理,
为什么memset写NULL值之后debug还可以看到 pRoot->childs里面有两个push进去的点,按照这个道理如果是清空childs.vector内存写了NULL值肯定push的时候就会debug断下出错
就好像你创建一个指针然后指向new一个空间,我突然把指针指向NULL,然后你在*p=写值进去肯定会出错
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-13 22:50:18 | 显示全部楼层
解决方案不是重要的,我是想知道其中的工作原理,这样以后用起来才会得心应手,不然总感觉没有搞懂
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-14 19:13:50 | 显示全部楼层    本楼为最佳答案   
zy8818 发表于 2021-11-13 19:45
什么原理?我用debung调试模式看注释和不注释memset的情况下 pRoot->childs下面都有两个push进去的对象 ...

这个原理很复杂(我dubug了半天也没搞清楚),但你不需要知道
原因很简单:原理不具有可移植性。
具体点说,对vector这种不具有内存平凡型的类使用memset()这类字节操作是未定义行为,这之后的一切行为都由编译器实现决定。我用Mingw测试的时候push_back()没有问题,用iterator遍历也没有问题。但用VS2019测试时push_back()没有问题,用iterator遍历出了问题。
写C++一定要牢记一个原则:永远不要尝试未定义行为,更不要尝试探究未定义行为背后的原理,因为换一个编译器(甚至是升级一个版本),其原理就会发生改变。知道其中的工作原理不仅不会让你用起来得心应手,还会让你撞得头破血流。请相信我学C++这几年的经验下次离未定义行为越远越好
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-16 10:21:45 | 显示全部楼层
lhgzbxhz 发表于 2021-11-14 19:13
这个原理很复杂(我dubug了半天也没搞清楚),但你不需要知道
原因很简单:原理不具有可移植性。
具体 ...

我明白了,你的意思是说不能把c语言那种赤裸裸可以自己完全把控的结构来用到高级语言c++的结构中来,
如果是纯c,纯自己结构体用memset就不会有问题
说白了用别人的高级语言就的遵守他的规则,所以memset只实用与c
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-16 10:27:50 | 显示全部楼层
兄弟你讲的太对了,编译器的工作原理事情,只能让编译器去头痛,如果出bug肯定是自己的原因,原因就是不符合编程语言的规则
只要明白这个道理,谁的语言规则谁做主,遵守他的规则就行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-16 10:41:12 | 显示全部楼层
memset只适合用在普通变量类型上面(例如int ,char[],int[],……等等)就是高级语言也是没有问题的,所以大家谨慎使用memset格式化高级语言的结构体或者高级类型,没准哪天bug就出来了,而且还不知道是哪里出问题了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-10 11:13

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表