2010-07-30 2 views
2

Это вопрос управления памятью о коде C++.Управление памятью

using namespace std; 
#include <iostream> 
#include <string.h> 

int main() 
{ 
string a="first"; 
string *b= new string; 
*b=a; 
a="second"; 
cout << *b << ", " << a; 
delete b; 
return 0; 
} 

Мы можем освободить блоки памяти, в которых сохранена строка, на которую указывает b. Я предполагаю, что это означает, что b больше не имеет никакого значения, как только это будет сделано. Мы можем освободить память, чтобы освободить память. Почему мы не можем освободить? Я знаю, что мы можем только удалить/бесплатно указатели, но строка a должна занимать какую-то память. Есть ли способ освободить память, которую занимает строка a? Если количество строк инициализировано так же, как и инициализировано a, возможно ли, что память закончится?

ответ

0

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

4

Строка a объявлена ​​в стеке. Вы не можете вручную освободить его, но он будет автоматически освобожден после того, как он покинет область действия (например, когда возвращается функция закрытия). Если вам нужно освободить эту среднюю память, тогда объявите ее динамически (как и для b).

+0

+1 Ваш ответ более полный, чем мой. – karlphillip

+0

Или вы можете заключить строку в меньшем объеме ... не то, что в большинстве случаев это будет стоить. –

2

Автоматические объекты (например, ваши а) уничтожаются, когда они выходят из сферы действия. Смотрите пример ниже:

int main() 
    { 

    { 
    string a="first"; 
    string *b= new string; 
    *b=a; 
    a="second"; 
    cout << *b << ", " << a; 
    delete b; //b gets freed 
    } //a gets freed because it has gone out of scope 
/* You can write more code here that does not need a */ 
return 0; 

}

0

a здесь автоматически выделяется на «стек», и будет автоматически уничтожен/высвобождены, когда он выходит из области видимости.

Когда вы используете динамическую память с new/malloc, она получает выделение на «кучу», которая представляет собой всего лишь кучу памяти, доступной для программы. Вам нужно управлять этим вручную, и программа не знает, когда его избавиться.

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

Edit: Это дает более полное объяснение, чем то, что я пытаюсь сказать: http://en.wikipedia.org/wiki/Malloc#Rationale

3

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

Вызов clear(), или назначение из строки emptry, может не освободить хранилище. Способ убедиться, что он освобожден, заключается в замене строки с помощью недавно созданного временного; временный деструктор освободит его.

string().swap(a); // replaces `a` with an empty string 

Вы также можете сделать это с помощью любого из стандартных контейнеров.

3

Это довольно неудобно.

<string.h> является заголовком C. Он не определяет string. Похоже, ваша версия <iostream> прямо или косвенно включает в себя <string>, или возникла бы ошибка.

Литеральные строки (те, которые ограничены парными кавычками) могут быть в любом месте, включая сегмент памяти только для чтения. (Они занимают память, но у вас есть очень много текста, чтобы иметь существенное влияние: что-то вроде Война и мир не собирается принимать полную мегаполию.) В этом случае std::string инициализируется этим значением, а затем имеет другое присвоенное ему значение. std::string обрабатывает память, которую он использует.

В C++ почти нет причин иметь указатель на std::string. std::string не занимает много места без его содержимого, и он управляет памятью для самого содержимого. Вы путаете это с char *?

Вы newstd::string для b, а затем назначить другой адрес для b без delete ИНГ памяти. Это утечка памяти. То, что вы new ed для b по-прежнему выделяется там, но нет никакого пути к delete, поэтому он будет занимать память на время работы программы.

Затем, как только вы присвоили адрес a по адресу: b, вы delete b;. Это плохая идея и, вероятно, испортит что-то важное, вероятно, непредсказуемым образом. Только delete память, которую вы приобрели с new. (Важно здесь delete Инг не то, что b является указателем и должны быть удалены, но в памяти он указывает не получил через new.)

управление Память работает примерно так. Строковый литерал где-то выделяется. Все, что вы знаете, это то, что вы не должны пытаться его изменить или delete это любым способом. Используйте значение и не трогайте остальные. A std::string управляет памятью для собственного содержимого и позаботится об этом в своем деструкторе. Переменная, объявленная в функции или в другом блоке, будет уничтожена после того, как она выходит из области видимости (хотя все, что она указывает на это, не будет автоматически уничтожаться, только если это умный указатель или управляет собственной памятью или что-то еще). Если вы используете память new, не выбрасывайте значение указателя до тех пор, пока оно не будет delete d. Если у вас нет new ed memory, не делайте delete.

+0

+1 для подробного объяснения кода. – rturrado

+0

Хм, на самом деле там нет утечки памяти: автор написал 'string * b = new string; * b = a; ' Ошибка утечки памяти, если он написал: ' string * b = новая строка; b = & a; ' Согласитесь с другими вашими заявлениями. – Haspemulator

+0

+1 Для упоминания строковой памяти памяти. Они обычно находятся в статической памяти приложения, а не в стеке или куче. Вот почему вы НИКОГДА не должны удалять указатель на строковый литерал. – Zoomulator

Смежные вопросы