Вектор вызова деструкторов при перераспределении - PullRequest
1 голос
/ 29 апреля 2020

У меня есть динамически размещенный трехмерный массив указателей на класс:

class Foo {
public:
    int a;
    float b;
    float c;
    Foo(int x, float y, float z) { a = x; b = y; c = z; }
};

в классе:

class Bar {
public:
    Foo ****p_arr;

    Bar();
    ~Bar();
    void Create();
};

, выделенный так (в Bar::Create()):

p_arr = new Foo***[ARR_SIZE];
for (unsigned int i = 0; i < ARR_SIZE; ++i) {
    p_arr[i] = new Foo**[ARR_SIZE];
    for (unsigned int j = 0; j < ARR_SIZE; ++j) {
        p_arr[i][j] = new Foo*[ARR_SIZE];
        for (unsigned int k = 0; k < ARR_SIZE; ++k) {
            if (rand() % (k + 1) < 1)
                p_arr[i][j][k] = new Foo(i, j, k * 0.1f);
            else
                p_arr[i][j][k] = nullptr;
        }
    }
}

И я хочу удалить его (в ~Bar()):

for (unsigned int i = 0; i < ARR_SIZE; i++) {
    for (unsigned int j = 0; j < ARR_SIZE; j++) {
        for (unsigned int k = 0; k < ARR_SIZE; k++) {
            if (p_arr[i][j][k] != nullptr)
                delete p_arr[i][j][k];
        }
        delete[] p_arr[i][j];
    }
    delete[] p_arr[i];
}
delete[] p_arr;

У меня есть std::vector Bar с, и когда я push_back к вектору new item, вектор перераспределяется и вызывает деструктор. Когда я снова получаю доступ к p_arr, он освобождается, и в деструкторе происходит сбой программы. Там написано:

0xC0000005: Access violation reading location 0xFFFFFFFF.

Здесь вылетает:

if (p_arr[i][j][k] != nullptr) // <- here
    delete p_arr[i][j][k];

Как это исправить?

Ответы [ 2 ]

0 голосов
/ 30 апреля 2020

Вы можете использовать одномерный массив для хранения N-мерных массивов, если размеры N-1 имеют одинаковый фиксированный размер, как у вас здесь. Таким образом, требуется только 1 выделение памяти, что улучшает использование памяти и локальность и устраняет все ненужные сложности.

Пример:

#include <memory>

struct Foo {
    int a = 0;
    float b = 0;
    float c = 0;
};

int constexpr ARR_SIZE = 10;

Foo& at(std::unique_ptr<Foo[]> const& a3d, unsigned i, unsigned j, unsigned k) {
    return a3d[(i * ARR_SIZE + j) * ARR_SIZE + k];
}

int main () {
    std::unique_ptr<Foo[]> a3d{new Foo[ARR_SIZE * ARR_SIZE * ARR_SIZE]};
    at(a3d, 0, 0, 0) = {1,2,3};
}

Вместо std::unique_ptr<Foo[]> вы можете использовать std::vector<Foo> - последний копируемый.

0 голосов
/ 30 апреля 2020

Я только что добавил конструктор копирования в Bar, и код работает нормально.

...