RAD Studio 10.2 (C ++): деструктор ~ TControl () работает только на каждой второй итерации - PullRequest
0 голосов
/ 12 октября 2018

Каждый раз, когда я пытаюсь запустить деструктор ~TControl(); на некоторых дочерних элементах управления (компонентах) TPanel, которые были созданы во время выполнения, он разрушает только каждую секунду дочернюю панель (например, см. Код ниже).

for(int i=0; i < ParentPanel->ControlCount; i++)
{
    ParentPanel->Controls[i]->~TControl();
}

Уничтожает оставшиеся дочерние элементы управления TPanel только в том случае, если я снова и снова запускаю цикл for (я понятия не имею, почему).

Теперь, если я попытаюсь запрограммировать его на 'вручную'уничтожить все дочерние элементы управления, которые я собираюсь создать во время выполнения (скажем, 4 дочерних элемента управления TPanel), это дает мне ошибку "List index out of bounds(#)", где # - это половина общего числа элементов управления, которые я создаюи скажите, чтобы он уничтожил вручную.

ParentPanel->Controls[0]->~TControl();
ParentPanel->Controls[1]->~TControl();
ParentPanel->Controls[2]->~TControl();
ParentPanel->Controls[3]->~TControl();

Например, приведенное выше может вызвать ошибку "List index out of bounds (2)".

То же самое происходит, даже если вместо этого я использую метод delete ParentPanel->Controls[0];.

Есть какие-нибудь подсказки?Ваша помощь очень ценится.Заранее спасибо.

Ответы [ 3 ]

0 голосов
/ 12 октября 2018

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

for (int i = ParentPanel->ControlCount - 1; i >= 0; i--)
{
    delete ParentPanel->Controls[i];
}

Проблема с подсчетом

Такие списки обычно сдвигают все элементы "выше" (с более высоким индексом)вниз, поэтому если Controls [i] был удален, теперь новый элемент управления перемещается в этот индекс.Но непосредственно после этого индекс увеличивается, так что он указывает на элемент выше того, который заменил удаленный, и только тот, который удален.Таким образом, по сути, удаляется только каждый второй элемент.

Initially:      [A]  B   C   D   E   F   G   H   I   J    i = 0

Индекс обозначается [ ]

Теперь вы удаляете и таким образом удаляете A, поэтомуновый порядок:

                [B]  C   D   E   F   G   H   I   J        i = 0

Но цикл немедленно увеличивает индекс:

                 B  [C]  D   E   F   G   H   I   J        i++, so i = 1 

, поэтому в следующем цикле C удаляется (что означает, что B пропускается).И так далее.Это означает, что удаляется только каждый второй элемент.

Но если вы начинаете сверху, никакие элементы не перемещаются, поэтому все удаляется.

Вызов деструктора

Мне кажетсякрайне плохая идея вызвать деструктора напрямую.Вместо этого используйте delete.

Компоненты

Обратите внимание, что если вы хотите удалить все компоненты, вы должны использовать список Components и ComponentCount.

0 голосов
/ 19 октября 2018

Вам нужно удалить элементы управления вместо вызова деструктора.

while(ParentPanel->ControlCount > 0)
    delete ParentPanel->Controls[0];
0 голосов
/ 12 октября 2018

Как сказал @Axbor Axrorov, размер массива уменьшался при уничтожении / удалении каждого дочернего элемента управления.

Я обнаружил, что одним из способов сделать это было использование оператора декремента.-- при удалении дочерних элементов управления, так что при увеличении целого числа в цикле for он продолжает удалять первый элемент в массиве, продолжая уменьшаться в размере (см. Код ниже).

for(int i=0; i<ParentPanel->ControlCount; i++)
{
    if(ParentPanel->Controls[i] != NULL)
    {
        delete ParentPanel->Controls[i--];
    }
}
...