Удаление элементов из динамических массивов без изменения порядка индекса - PullRequest
0 голосов
/ 05 сентября 2011

Я пытался стереть элемент из массива без изменения порядка индекса, например:

class MyObject  
{  
    int id;  
public:  
    MyObject() { }  
    void setId( int i ) { id = i; }  
    void showId() { std::cout << "ID: "<< id << "\n"; }
};  
MyObject *myArray;

int main ( )  
{  
    myArray = new myArray[6];  
    for( int i = 0; i < 6; i++ )  
    {  
        myArray[i]->setId(i); 
        myArray[i]->showId();
    }  
}  

Я хочу удалить myArray[3] без изменения индекса других.Например:

myArray[0] = ID: 1  
myArray[1] = ID: 2  
myArray[2] = nothing  
myArray[3] = ID: 4  
myArray[4] = ID: 5  
myArray[5] = ID: 6    

Я пытался использовать memset(), но это не сработало.

memset(&myArray[3],0,sizeof(MyObject));

Ответы [ 4 ]

1 голос
/ 05 сентября 2011

В языке C ++ не существует понятия "ничего". Если у вас есть массив, все элементы этого массива будут содержать «что-то». Нет никакого способа заставить элемент массива просто исчезнуть , сохранив все остальные элементы на прежних местах. Вы не можете создать дыру в массиве.

Все, что вы можете сделать в этом случае, это просто пометить некоторый элемент как «удаленный», а затем позже распознать его как таковой. Элемент, конечно, будет продолжать существовать физически. Именно вам придется распознавать его как «удаленный» и игнорировать его при дальнейшей обработке. Вы можете добавить поле bool is_deleted к своему объекту или использовать зарезервированное значение id (например, -1), чтобы указать удаленный элемент.

В вашем примере с memset вы по существу устанавливаете id в ноль. Является ли 0 допустимым id значением? Если это не так, тогда 0 - хороший выбор, чтобы отметить удаленный элемент. В этом смысле ваша попытка memset работает отлично, как и должно быть. Хотя я бы порекомендовал сделать это, явно присвоив ноль id, без использования memset.

0 голосов
/ 05 сентября 2011

Используя memset, вы устанавливаете все байты этого объекта в 0. Обычно это эквивалентно установке id в 0, потому что память объекта - это память его членов (не считая vtables, padding)., так далее).Но не делайте этого в любом случае.

Один из способов сделать это - использовать new и иметь массив указателей.

MyObject* myArray[6];

int main ( )  
{ 
    for( int i = 0; i < 6; i++ )  
    {
        myArray[i] = new MyObject;
        myArray[i]->setId(i); 
        myArray[i]->showId();
    }  
}

Затем отобразить их все:

for (int i = 0; i < 6; i++) {
    cout << "myArray[" << i << "] = ";
    if (myArray[i])
        myArray[i]->showId();
    else
        cout << "nothing" << endl;
}

Затем, когда вы хотите удалить объект, delete он и устанавливает его указатель на NULL:

delete myArray
myArray[3] = NULL;

Затем, когда вы что-нибудь делаете с одним из объектов в myArray, вы должны проверить, является ли это NULL, чтобы видеть, является ли это действительным объектом.

0 голосов
/ 05 сентября 2011

Рассмотрим boost :: необязательно :

typedef boost::optional<MyObject> MyObjectOpt;
MyObjectOptArr *myArray;

Синтаксис / использование немного отличается (похоже на использование указателя):

for (int i = 0; i < 6; ++i) {      
    if (myArray[i])
        cout << "myArray[" << i << "] = " << *(myArray[N]);
    else
        cout << "nothing" << endl;
}

Для сброса значенияделать:

myArray[N] = boost::none;
0 голосов
/ 05 сентября 2011

Вы звоните memset, чтобы написать группу нулей поверх экземпляра объекта. Не делайте этого! Вам может это сойти с рук, если ваш класс - настоящий POD-класс. В конечном итоге вы можете просто установить идентификатор в 0. Но, возможно, в вашем классе есть еще что-то, чего вы не показываете. В любом случае, даже если это не POD, не используйте memset как этот.

Вы можете хранить указатели на объект и использовать нулевой указатель, чтобы указать, что там ничего нет. Я бы сделал это с std::vector<MyObject*>. Или вы используете экземпляр объекта-стража, например, с идентификатором -1.

Другая проблема, которая может быть проблемой, заключается в том, что вы, похоже, используете индексы на основе 1. Массивы C ++ основаны на 0, поэтому первый элемент - myArray[0], а не myArray[1].

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...