zy8818 发表于 2021-11-13 11:15:25

vector 出错 vector iterators incompatible

本帖最后由 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("|"));
        }

lhgzbxhz 发表于 2021-11-13 19:27:23

好家伙,memset(pNew, 0, sizeof(TreeNode))直接把vector的内存置零了,不出bug才怪
直接pNew->pParent = 0;就行了

zy8818 发表于 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进去的对象

zhsguitar 发表于 2021-11-13 22:09:44

pNew->pParent = 0我也跟着学习一下 混点鱼币{:10_257:}

zy8818 发表于 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=写值进去肯定会出错

zy8818 发表于 2021-11-13 22:50:18

解决方案不是重要的,我是想知道其中的工作原理,这样以后用起来才会得心应手,不然总感觉没有搞懂

lhgzbxhz 发表于 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++这几年的经验下次离未定义行为越远越好

zy8818 发表于 2021-11-16 10:21:45

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

我明白了,你的意思是说不能把c语言那种赤裸裸可以自己完全把控的结构来用到高级语言c++的结构中来,
如果是纯c,纯自己结构体用memset就不会有问题
说白了用别人的高级语言就的遵守他的规则,所以memset只实用与c

zy8818 发表于 2021-11-16 10:27:50

兄弟你讲的太对了,编译器的工作原理事情,只能让编译器去头痛,如果出bug肯定是自己的原因,原因就是不符合编程语言的规则
只要明白这个道理,谁的语言规则谁做主,遵守他的规则就行

zy8818 发表于 2021-11-16 10:41:12

memset只适合用在普通变量类型上面(例如int ,char[],int[],……等等)就是高级语言也是没有问题的,所以大家谨慎使用memset格式化高级语言的结构体或者高级类型,没准哪天bug就出来了,而且还不知道是哪里出问题了
页: [1]
查看完整版本: vector 出错 vector iterators incompatible