область указателя c ++ - PullRequest
       11

область указателя c ++

19 голосов
/ 31 декабря 2010

Что происходит, когда у вас есть следующий код:

void makeItHappen()
{
    char* text = "Hello, world";
}

Выходит ли text из области видимости и автоматически удаляется или он остается в памяти?

А как насчет следующего примера:

class SomeClass
{
    public:
      SomeClass();
      ~SomeClass();
};

SomeClass::SomeClass() { }
SomeClass::~SomeClass()
{
    std::cout << "Destroyed?" << std::endl;
}

int main()
{
    SomeClass* someClass = new SomeClass();
    return 0;
} // What happend to someClass?

Здесь происходит то же самое?

Спасибо!

Ответы [ 4 ]

24 голосов
/ 31 декабря 2010
 char* text = "Hello, world";

Здесь автоматическая переменная (указатель) создается в стеке и устанавливается для указания значения в постоянной памяти , что означает:

  • строковый литерал в "" существует в течение всего выполнения программы.
  • Вы не несете ответственности за его «распределение» или «освобождение»
  • вы не можете изменить его. Если вы хотите изменить его, вам нужно выделить некоторую «непостоянную память» и скопировать ее туда.

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

Для последнего:

SomeClass* someClass = new SomeClass();

Тогда указатель someClass также будет освобожден, когда он выйдет из области видимости (поскольку сам указатель тоже находится в стеке, только в первом примере) ... , но не объект!

Ключевое слово new в основном означает, что вы выделяете некоторую память для объекта в free store - и вы ответственны за вызов delete когда-нибудь, чтобы освободить эту память.

11 голосов
/ 31 декабря 2010

Выходит ли text из области видимости

Да!Он является локальным для функции makeItHappen() и, когда функция возвращается, выходит из области видимости.Однако указанный строковый литерал "Hello, world"; имеет статическую продолжительность хранения и хранится в разделе памяти, доступном только для чтения.

А как насчет следующего примера:

......
Здесь происходит то же самое?

Ваш второй кодОбразец утечки памяти.

SomeClass* someClass = new SomeClass();

someClass локально по отношению к main(), поэтому, когда main возвращает его, будучи автоматической переменной, уничтожается.Однако указанный объект остается в памяти, и нет возможности освободить его после возврата из функции.Вам нужно явно написать delete someClass, чтобы правильно освободить память.

6 голосов
/ 31 декабря 2010

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

Для объектов, которые вы выделяете с помощью новых (например, SomeClass), вам необходимо явно удалить их.Если вы хотите, чтобы объекты, расположенные таким образом, автоматически удалялись, посмотрите на boost smart smart pointers (std :: unique_ptr, если ваш компилятор поддерживает c ++ 0x).

Это автоматическиудалите выделенный объект, когда общий указатель выйдет из области видимости.

Ваш код будет выглядеть следующим образом:

int main(int argv, char **argv)
{
  boost::scoped_ptr<SomeClass> ptr(new SomeClass);
  // the object is automatically deleted
  return 0;
}

Примечание. В этом конкретном примере вы также можете использовать std ::auto_ptr (но это будет устаревшим в c ++ 0x).

Примечание 2: Как отмечалось в комментариях Коса, в этом случае более целесообразно использовать boost :: scoped_ptr или std ::unique_ptr (C ++ 0x).В моем ответе сначала использовался boost :: shared_ptr, который более уместен, если вам нужно разделить владение указателем, например, между несколькими классами.

1 голос
/ 31 декабря 2010

В первом примере строковый литерал хранится в сегменте данных вашего исполняемого файла.
Во втором случае вам не нужно вызывать delete (в вашем примере программа просто завершается), так как при завершении программы кучав любом случае освобожден для процесса.
Обратите внимание, что есть ОС (как я читал), что вам нужно явно освобождать кучу, даже если программа завершает работу, поскольку она не будет очищена при завершении для вас.
Конечнопрограммист отвечает за управление памятью в C ++, и объекты, которые вы создаете в куче, должны быть delete отредактированы, если они не нужны.

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