Как получить доступ к переменным, которые размещены в куче в C ++, даже после выхода из области видимости? - PullRequest
0 голосов
/ 29 октября 2019

У меня проблемы с пониманием нового ключевого слова в C ++. Я понимаю, что для того, чтобы память не высовывалась из стека после выхода из области видимости;Вы можете хранить его в куче. Однако в этом примере я получаю сообщение об ошибке «идентификатор p не определен»

#include <iostream>
#include <string>

class Person {
public: 
    int age; 
    std::string name;

    Person() {

    }

    Person(int a, std::string n): age(a), name(n){}
};


int main() {
    {
        Person* p = new Person(5, "bob");
    }

    std::cout << (*p).age; 

}

Как вы можете видеть в моей основной функции, я создал еще одну область видимости, в которой я создаю объект Person в куче, из чего язнать, что объект все еще будет существовать после выхода из фигурных скобок, но тогда почему он не распознает объект p?

Я пытался разыменовать p, но ошибка остается той же. Любая помощь будет отличной! Спасибо

Ответы [ 4 ]

1 голос
/ 29 октября 2019

Вы правы, что объект все еще существует, так как вы никогда не удаляли его. Это только половина вопроса, хотя. Имя p является локальным для вложенной области, в которой вы ее объявили. После выхода из этой области p уничтожается, и вы больше не можете получить доступ к созданному вами объекту.

То, что вам потребуетсябыть

int main() 
{
    Person* p;
    {
        p = new Person(5, "bob");
    }

    std::cout << (*p).age; 
}

и теперь вы можете получить доступ к p, поскольку он был объявлен в области действия main.

0 голосов
/ 29 октября 2019

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

И она умрет после окончания блока (сам указатель p, значение которого равно 32/64 в зависимости от вашегомашина). и память, выделенная новым, все еще находится в куче, но сам указатель - нет (что приведет к утечке памяти).

Я не знаю, что именно вы хотите сделать, но вы можете сделать

int main() {
Person * ptr;
    {
        Person* p = new Person(5, "bob");
        ptr = p;
    }

    std::cout << (*ptr).age;

    //free the memory if you will not use it anymore
    delete ptr;
}

Затем вы можете использовать ptr для указания на блок, созданный новым.

0 голосов
/ 29 октября 2019

Объект все еще там, и если вы не удалите его, у вас утечка памяти. Если вы хотите получить к нему доступ в другом месте, вам нужно сохранить ссылку на него (ссылка в общем смысле, то есть указатель или ссылка).

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

int main() {
    Person* p;
    {
        p = new Person(5, "bob");
    }
    std::cout << (*p).age; 
    delete p;
}
0 голосов
/ 29 октября 2019

Person* p - это объект типа Pointer* с автоматическим хранением («локальная переменная»). Этот указатель, как и любой объект с автоматическим хранением, существует только до конца области, в которой он был объявлен. Как только вы достигнете закрытия } области действия блока, которую вы создали, больше не будет такой вещи, как p, чтоуказатель перестал существовать

Хотя p не существует, то, на что он раньше указывал, все еще существует. Ваш Person слил и ушел. Без указателя или ссылки на него нет способа вернуть его назад и нет способа его очистить. Обязательно сохраняйте p или другой указатель на него, пока вы не delete сделаете это.

Перемещение объявления Person* p за пределы области действия (или полное удаление искусственной области действия) решит эту проблему. В этом случае время жизни p связано с областью действия main и будет существовать к тому времени, когда вы попытаетесь std::cout это age член.

Рассмотрите возможность использования умных указателей нахотя бы избегайте таких утечек. std::unique_ptr<Person> p автоматически delete Person, когда последний (и единственный) указатель перестает существовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...