Влияет ли установка указателя на nullptr на другие указатели, указывающие на тот же адрес?

Рассмотрим следующую функцию, которая удаляет узел из двоичного дерева поиска, если у узла нет дочерних элементов:

void erase_no_children(node* todel)
{
    //...
    if (todel->parent->left == todel) //if todel is left child
        todel->parent->left = nullptr;

    if (todel->parent->right == todel) //if todel is right child
        todel->parent->right = nullptr;

    delete todel;
}

Поскольку todel->parent->left == todel это означает, что, устанавливая todel->parent->left на nullptr, я точно так же устанавливаю todel на nullptr. Компилятор вообще не жалуется.

Вопрос. Безопасно ли это? Это течет? Или это неопределенное поведение?


person DeiDei    schedule 08.12.2015    source источник
comment
Вы не устанавливаете todel на nullptr.   -  person Barmar    schedule 08.12.2015
comment
Нет, вы не устанавливаете для todel значение nullptr. Вы устанавливаете для todel-›parent-›left значение nullptr. Судя по тому, что здесь показано, это безопасно и нет утечек памяти. Помните, что это указатели. Все, что они делают, это указывают на что-то. У вас может быть 100 указателей, указывающих на одну и ту же память, и установка для одного из них значения nullptr не повлияет на остальные 99.   -  person Christopher Schneider    schedule 08.12.2015
comment
Установка значения todel->parent->left не меняет значение todel.   -  person Galik    schedule 08.12.2015
comment
Повторное открытие, потому что, хотя на вопрос ОП уже дан ответ в виде дубликата, здесь есть фундаментальное недоразумение, на которое нужно ответить.   -  person Sebastian Redl    schedule 08.12.2015
comment
@SebastianRedl Спасибо за это. Я как раз собирался, когда ты это сделал.   -  person NathanOliver    schedule 08.12.2015


Ответы (3)


Поскольку todel->parent->left == todel это означает, что, устанавливая todel->parent->left на nullptr, я точно так же устанавливаю todel на nullptr.

Это неправильно. todel и todel->parent->left — разные переменные-указатели; установка одного на nullptr не влияет на другое.

Таким образом, вы не удаляете nullptr (что было бы безопасно и бесполезно).

person Sebastian Redl    schedule 08.12.2015
comment
Я понимаю. Так что я полагаю, что я неправильно понял корень проблемы! Изменил название соответственно... - person DeiDei; 08.12.2015

Ваша функция заключается в том, чтобы убедиться, что ваш узел недоступен (т. е. сделать его сиротой), чтобы можно было безопасно удалить его память. Ваше назначение значений Right и Left для nullptr вполне приемлемо, так как в нем говорится, что узел больше не является дочерним элементом своего родителя.

Вы освобождаете память, которая была выделена программе C++, записывая delete todel. Это может произойти только один раз. После того, как вы освободили память обратно в ОС, любые дальнейшие указатели на эту переменную теперь «устаревшие» (т. Е. Устаревшие)

Вы делаете правильную вещь, управляя каждым указателем по отдельности (связывая свободные концы), а затем удаляя оставшийся указатель.

Параметр todel->parent->left = nullptr не влияет на значение указателя, содержащееся в todel. Так же не освобождает память, которая была выделена от ОС на todel. Ваш оператор удаления делает; все ваши назначения для nullptr удаляют другие ссылки на эту память.

person J. Murray    schedule 08.12.2015

todel->parent->left и todel->parent->right — разные указатели на todel. Если они указывают на тот же объект, что и todel, то рекомендуется сбросить их, чтобы они указывали на ноль. Если вы оставите их установленными, у вас будут «висячие указатели», которые могут вызвать проблемы, которые, как известно, трудно отладить.

Обратите внимание, что delete todel; означает «Я закончил работу с объектом, на который указывает todel». Это может быть не так, если на этот объект указывает еще какая-то переменная!

person Toby Speight    schedule 08.12.2015