LINUX.ORG.RU

порядок удаления объектов класса, C++


0

1

всем привет, помогите пожалуйста! у меня есть класс myclass. его экземпляры динамически создаются и удаляются в процессе работы программы. доступ к экземлярам осуществляется через указатели, которые хранятся в векторе. vector <myclass *> vec1; vec1.push_back(new myclass());

в ходе работы любой объект из vec1 может быть удален. А нужно ли строго соблюдать порядок удаления ?? т.е. vec1[0] будет удален позже чем vec1[1];

соблюдать порядок удаления как и порядок создания - не надо.

А надо вот, что - прочитать учебник по С++.

MikeDM ★★★★★
()

А нужно ли строго соблюдать порядок удаления ?? т.е. vec1[0] будет удален позже чем vec1[1];

В общем случает нет. Исключение - если в программе есть какие-то побочные эффекты с этим связанные. Т.е. тебе должно быть виднее, имеет ли значение порядок уничтожения объектов.

m0rph ★★★★★
()
Последнее исправление: m0rph (всего исправлений: 1)

если класс non-copyable, определи для него myclass(myclass&&) и оператор myclass& operator =(myclass&&); и используй c++11 и метод emplace. но учти - в векторе объект будет двигатся, так что указатели на него нигде не храни. в остальном будет работать

ckotinko ☆☆☆
()
Ответ на: комментарий от ckotinko

спасибо, а в моем решении будут ошибки?

еще есть операции вида: vec1=vec2[j], где vector <myclass*> vec2;

и что значит «в векторе объект будет двигатся» ??

kolya38
() автор топика
Ответ на: комментарий от kolya38

затупил я. лучше уж vector<std::unique_ptr<myclass>> использовать

ckotinko ☆☆☆
()
Ответ на: комментарий от kolya38

а вот здесь говорят нужно

Плохо говорят. Проблема может быть, если один объект содержит ссылки или указатели на другой или его части, тогда удаление второго делает первый невалидным до момента его собственного удаления, например:

#include <cstdio>

int main()
{
    int *x = new int(42);
    int **y = new int*[1];
    y[0] = x;
    printf("%d %d\n", x[0], *y[0]);
    delete x;
    printf("%d\n", *y[0]);
    // ==30938== Invalid read of size 4
    // ==30938==    at 0x40083A: main (in /tmp/a.out)
    // ==30938==  Address 0x59f9040 is 0 bytes inside a block of size 4 free'd
    // ==30938==    at 0x4C2AF3C: operator delete(void*) (vg_replace_malloc.c:480)
    // ==30938==    by 0x40082A: main (in /tmp/a.out)
    // ==30938== 
    delete[] y;
}

или

#include <cstdio>

struct A {
    int x;
    int y;
    struct AA {
        int x;
        int y;
    } xy;
};

struct B {
    int x;
    int y;
    A::AA &aa;
};

int main()
{
    A *a = new A{1, 2, {3, 4}};
    B *b = new B{5, 6, a->xy};
    printf("%d %d\n", a->x, b->aa.x);
    delete a;
    printf("%d\n", b->aa.x);
    delete b;
}

Но это никакой не «принцип кучи», то есть роль играет не порядок удаления относительно порядка создания, а то как устроен направленный граф описывающий как связаны ссылочно объекты, и тут нужно учитывать, что связь может быть на «обычную» часть или на часть со связью на ещё третий объект, во втором случае участники цикла второго типа в таком графе должны удаляться все вместе, а вообще удаление какого-то объекта делает невалидными все объекты выше по графу — все соседи независимо от типа связи и всё выше по связям второго типа. Из этого надо исходить, так что тебе должно быть видней как связаны (если вообще связаны) объекты vector<myclass*>.

З.Ы. «невалидным» значит, его использование _может_ привести к ошибкам времени выполнения, это не значит что его нельзя _как-то_ использовать не получая ошибок.

quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 2)

Не нужно, если конечно не удалять родителей раньше потомков, может случится что-то очень плохое...

Human-source
()

vector <myclass *> vec1; vec1.push_back(new myclass());

К слову, этот код не exception-safe: если new myclass() выполнится успешно, а реаллокация вектора в push_back кинет исключение, экземпляр myclass утечёт.

slovazap ★★★★★
()

ок ребята, всем спасибо!

kolya38
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.