Подтвердить что ты не робот

Область указателей С++

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

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?

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

Спасибо!

4b9b3361

Ответ 1

 char* text = "Hello, world";

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

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

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

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

SomeClass* someClass = new SomeClass();

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

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

Ответ 2

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

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

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

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

Второй образец кода просачивает память.

SomeClass* someClass = new SomeClass();

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

Ответ 3

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

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

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

Тогда ваш код будет выглядеть так:

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

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

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

Ответ 4

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