Нужно ли удалять элементы при уменьшении массива? - PullRequest
2 голосов
/ 30 октября 2010

Я студент, пишущий метод, который удаляет нули из конца массива целых чисел в C ++.Массив находится в структуре, и в структуре также есть int, который отслеживает длину массива.

Метод проверяет каждый элемент, начиная с последнего, до тех пор, пока не встретит первый ненулевой элемент,и помечает его как «последний элемент», изменяя значение длины.Затем метод возвращается к исходному «последнему элементу», удаляя те элементы, которые не выходят за пределы (нули).

Часть, которая удаляет i -й элемент в массиве, если i больше обновленной длины массива, выглядит так:

if (i > p->length - 1) {
  delete (p->elems + i); // free ith elem

Эта строка, однако, неверна.Удалить берет указатель, да?Поэтому я чувствую, что мне нужно восстановить указатель на массив, а затем добавить к нему i, чтобы у меня в памяти было целое число, которое я хочу удалить.

Неужели моя интуиция неверна?Ошибка тонкая?Или я правильно понял?Я начал задаваться вопросом: действительно ли мне нужно освободить эти примитивы?Если бы они не были примитивами, мне бы это понадобилось, и в таком случае, как бы я?

Ответы [ 2 ]

5 голосов
/ 30 октября 2010

я правильно понял?

Боюсь, что так.

Если вы сделаете один new[] вызов для выделения массива, то вынеобходимо сделать один delete[] вызов, чтобы освободить его:

int *p = new int[10];
...
delete[] p;

Если ваш массив находится в структуре, и вы делаете один вызов для выделения структуры, то вы должны сделать один вызов для ее освобождения:

struct Foo {
    int data[10];
};

Foo *foo = new Foo;
...
delete foo;

Невозможно освободить часть массива.

Массив int[10] на самом деле - это 10 целых чисел подряд (то есть 40 байтовпамять в 32-битной системе, возможно, плюс накладные расходы).Целое число значений , которые хранятся в массиве, занимают эту память - они сами по себе не выделяются, и их не нужно освобождать.

Все, что сказано, если вы хотите переменнуюмассив длины:

вот что такое std :: vector для

#include <vector>
#include <iostream>

struct Foo {
    std::vector<int> vec;
};

int main() {
    Foo foo;

    // no need for a separate length: the current length of the vector is
    std::cout << foo.vec.size() << "\n";

    // change the size of the vector to 10 (fills with 0)
    foo.vec.resize(10);

    // change the size of the vector to 7, discarding the last 3 elements
    foo.vec.resize(7);
}
3 голосов
/ 30 октября 2010

Если p->elems - указатель, то и p->elems + i (при условии, что операция определена, т. Е. I имеет целочисленный тип) - и p->elems + i == &p->elems[i]

Во всяком случае, вы, скорее всего, нехотите (и не можете) удалить целые из массива int (будь то динамически или автоматически).Это

int* ptr = new int[10];
delete &ptr[5]; // WRONG!

Это просто то, что вы не можете сделать.Однако, если структура содержит длину массива, вы можете считать массив «измененным» после изменения информации о длине, содержащейся в структуре - в конце концов, невозможно определить размер массива, на который указывает указатель.

Если, однако, ваш массив представляет собой массив указателей на целые числа (int*[]), и эти указатели указывают на динамически распределенную память, тогда да, вы можете удалить отдельные элементы и сделать это по строкамваш код (вы показываете так мало кода, трудно быть точным).

...