Интересная проблема при попытке сброса указателя - PullRequest
1 голос
/ 12 июля 2011

То, что мой C ++ не так уж велик, это может быть очень простой / очевидный ответ, но это наверняка поставило меня в тупик.Имейте в виду, это немного поздно здесь, и я немного устал.Я получил этот код здесь:

void TestFunc(int *pVar)
{
    cout << endl << *pVar << endl;
    delete pVar;
    pVar = nullptr;
}

int main(int argc, char *argv[])
{
    int *z(new int);

    *z = 5;
    TestFunc(z);
    if (z == nullptr)
        cout << "z Successfully Deleted!" << endl;
    else cout << "z NOT deleted!" << endl;
    return 0;
}

Программа прекрасно компилируется без ошибок и предупреждений.Когда я запускаю его, он отображает 5, как я и ожидал.Тем не менее, это говорит z NOT deleted!.Мне любопытно, почему pVar не устанавливается на nullptr, хотя я просто установил его в своей функции TestFunc ().Любая помощь будет оценена.Если это имеет значение, это Visual Studio 2010 и просто обычное неуправляемое приложение C ++.

Ответы [ 4 ]

5 голосов
/ 12 июля 2011

Поскольку он передается по значению (то есть как копия).

Если вы хотите, чтобы передавалась переменная сама (а не только ее значение,скопировано), используйте

void TestFunc(int *&pVar)

.

Обратите внимание, что delete заботится только о pointee , а не о указателе .Таким образом, «удаление» копии указателя удаляет то же самое, что и исходный указатель, потому что в любом случае вы удаляете их цели, которые совпадают.

2 голосов
/ 12 июля 2011

TestFunc принимает указатель по значению, поэтому установка его в null внутри функции фактически влияет только на копию в функции и не видна вызывающей стороне.Таким образом, pVar имеет значение null, но z в main() не потому, что это разные переменные.

Чтобы сделать видимым для вызывающего изменения изменение, передайте указатель по ссылке или через двойной указатель.

1 голос
/ 12 июля 2011

Уже поздно (извините !!!).

z передается по значению. z не pVar. Вы присвоили значение nullptr pVar, а не z.

0 голосов
/ 12 июля 2011

Представляемая вами идиома обычно обозначается как Безопасное удаление .

Она уже была известна в C (хотя в то время это была free): обнулитьуказатель, который вы только что освободили / удалили, чтобы избежать этого дважды.

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

Работа с памятью - сложная тема, фундаментальная концепция - владение .В любой момент времени владельцы определенной зоны памяти должны быть четко определены, и они должны нести ответственность за их возврат в систему, когда это необходимо.

Первый шаг в этомНаправление - это использование умных указателей, например std::unique_ptr или boost::scoped_ptr.Для совместного владения (только для экспертов) std::shared_ptr может пригодиться, но вы еще не пришли.

Если вы пишете delete в своем коде, это означает, что вы подвергаете себя утечкам.Это само по себе неплохо, но требует тщательного анализа и делает код хрупким (то есть может сломаться при изменении).В вашем случае:

int main() {
  boost::scoped_ptr<int> i(new 5);
  foo(*i);
} // memory returned to system by ~scoped_ptr()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...