C ++:从动态结构数组中删除元素并转移其他元素 [英] C++: Remove element from dynamic struct array and shift other elements

查看:118
本文介绍了C ++:从动态结构数组中删除元素并转移其他元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个结构体数组.我正在尝试从该数组中删除元素列表,并将其他元素移到左侧.转移元素后,我试图删除/释放不再需要的数组末尾的内存.我有以下代码:

I have an array of structs. I am trying to delete a list of elements from that array and shift other elements to the left. After shifting the elements I am trying to delete/free the memory at the end of the array which we don't require anymore. I have the following code:

#include <iostream>
#include<stdio.h>
#include<stdlib.h>
void removeelement(int*);
void displayelements();

typedef struct {
   int n;
}element;
element** array;

int numofelements=5;

int main() {
   array = (element**)malloc(5*sizeof(element*));
   for(int i=0;i<5;i++){
       array[i] = new element;
       array[i]->n=i;
   }
   int removelist[3] = {1,3,4};
   removeelement(removelist);
   displayelements();
   return 0;
}
void removeelement(int* removelist){
    for(int i=0;i<3;i++){
        int index = removelist[i];
        int j;
        for(j=index;j<numofelements-2;j++){
            array[j] = array[j+1];
        }
        delete [] array[j+1];
        numofelements--;
    }
}
void displayelements(){
    int i=0;
    while(i<numofelements){
        printf("%d\n",array[i]->n);
        i++;
    }
}

但是delete [] array[j+1];导致异常:

*** Error in `main': double free or corruption (fasttop): 0x0000000001861cb0 ***

我不明白是什么原因造成的.正如许多人在其他论坛上所建议的那样,我正在使用"new"运算符创建一个新的动态元素.

I don't understand what's causing this. As many people have suggested in other forums, I am using the 'new' operator to create a new,dynamic element.

我进行了以下更改:

我将for(j=index;j<numofelements-2;j++){更改为for(j=index;j<numofelements-1;j++){

int index = removelist[i]int index = removelist[i]-i

我删除了delete [] array[j+1]delete array[numofelements+1]放在两个for循环之外. 尽管我只在一个元素上使用了delete,但它也为其他冗余元素分配了内存,这很有趣. 这是最终的代码:

I removed delete [] array[j+1] put delete array[numofelements+1] outside both the for loops. Though I had used delete only on one element, It dealloced memory for the other redundant elements as well, which is interesting. This is the final code:

#include <iostream>
#include<stdio.h>
#include<stdlib.h>
void removeelement(int*);
void displayelements();

typedef struct {
   int n;
}element;
element** array;

int numofelements=5;

int main() {
   array = (element**)malloc(5*sizeof(element*));
   for(int i=0;i<5;i++){
       array[i] = new element;
       array[i]->n=i;
   }
   int removelist[3] = {1,3,4};
   removeelement(removelist);
   displayelements();
   return 0;
}
void removeelement(int* removelist){
    for(int i=0;i<3;i++){
        int index = removelist[i]-i;
        int j=index;
        for(;j<numofelements-1;j++){
            array[j] = array[j+1];
        }
        numofelements--;
    }
    delete array[numofelements+1];
}
void displayelements(){
    int i=0;
    while(i<5){
        printf("%d\n",array[i]->n);
        i++;
    }
}

我使用此代码正常工作.但是我将按照你们许多人的建议使用std :: vector.

I got it working using this code. But I am going to use std::vector as many of you suggested.

推荐答案

除了内存管理中的明显错误外,如果您首先对removelist数组进行排序,然后再进行反向操作,则通常可以简化该方法.从最后一个条目到第一个条目的数组.

Apart from the obvious errors in memory management, the approach in general could have been made simpler if you first sorted the removelist array, and then work backwards in that array starting from the last entry going toward the first entry.

这样做将改变array调整大小的方式,因为您将对不再受影响的条目进行调整大小(移动元素).在当前代码中,您正在移动条目,并且在循环的后续迭代中,您需要使用现在要删除的无效" removelist索引集重新访问那些已移动的条目.

Doing this would have changed the way the array was being resized in that you would have been doing the resizing (shifting elements) on entries that will no longer be affected. In your current code, you are shifting entries, and in subsequent iterations of the loop, you need to revisit those shifted entries with a now "invalid" removelist set of indices to remove.

请参见mayaknife和user2079303的答案,以说明删除每个项目后无效条目的问题(从removelist数组中的最低条目到最高条目).如前所述,即使使用std::vector也不会帮助您,因为此问题指出了用于删除元素的基本逻辑中的缺陷.

See mayaknife's and user2079303 answers to illustrate the issue of invalid entries after removing each item (going from lowest entry to highest entry in the removelist array). As pointed out, even a usage of std::vector would not have helped you, since this issue points out the flaw in the basic logic being used to remove the elements.

如果要在removelist数组中向后移动,则可能会在当前代码中解决此问题(我说可能已解决",因为尚未经过充分测试,但这或多或少说明了这一点)提出的要点):

Here is how you might have addressed this in your current code if you were to work going backwards in the removelist array ( I say "might have addressed", since this is not fully tested, but it illustrates more or less the point being made):

void removeelement(int* removelist)
{
    for(int i = 2; i >= 0 ; --i)
    {
        int index = removelist[i];
        array* elementToDelete = array[index];
        for(j=index; j < numofelements -2; j++)
        {
            array[j] = array[j+1];
        }
        delete [] elementToDelete;
        numofelements--;
    }
}

因此,在每次迭代中,removelist索引仍然有效,因为您将从要删除的条目中的最高条目到最低条目.在纸上解决这个问题,然后看看是否颠倒了遍历removelist数组的方式,您应该了解它的工作原理,而不是继续遍历removelist数组.

Thus on each iteration, the removelist index will still be valid, since you're going from highest entry to lowest entry in the entries to delete. Work this out on paper and you see if you reversed the way you iterated through the removelist array, you should see how this works, as opposed to going forward through the removelist array.

您的代码还存在其他问题,例如将mallocdelete[]混合使用.这样做是不确定的行为-切勿在C ++程序中混合使用这种分配/释放方法.

You also have other issues with the code, such as mixing malloc with delete[]. Doing so is undefined behavior -- never mix allocation / deallocation methods like this in a C++ program.

话虽如此,这是您程序的另一个版本,但未使用手动内存管理:

Having said this, here is another version of your program, but not using manual memory management:

#include <vector>
#include <algorithm>
#include <iostream>
#include <array>

struct element {
   int n;
};

int main() 
{
    std::vector<element> arr(5);

    for (int i = 0; i < 5; ++i)
       arr[i].n = i;

    std::array<int, 3> removelist = {1,3,4};
    // sort the list 
    std::sort(removelist.begin(), removelist.end());

    // work backwards, erasing each element
    std::for_each(removelist.rbegin(), removelist.rend(),[&](int n){arr.erase(arr.begin() + n);});

    // output results
    for( auto& v : arr)
       std::cout << v.n << '\n';
}

实时示例

请注意反向迭代器rbegin()rend()的用法,因此模仿了removelist容器的向后遍历.

Note the usage of the reverse iterators rbegin() and rend(), thus mimicking the backwards traversal of the removelist container.

这篇关于C ++:从动态结构数组中删除元素并转移其他元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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