Есть ли необходимость уничтожить char * = «строка» или char * = new char[6]?
Вопрос
Я предполагаю, что char* = "string"
то же самое, что char* = new char[6]
.Я считаю, что эти строки создаются в куче, а не в стеке.Так нужно ли мне уничтожать их или освобождать их память, когда я закончу их использовать, или они уничтожатся сами по себе?
Решение
Нет.Вам нужно вручную освобождать строки только тогда, когда вы вручную выделяете память с помощью malloc
функция (в C) или new
оператор (в C++).Если вы не используете malloc
или new
, тогда char*
или строка будет создана в стеке или как константа времени компиляции.
Другие советы
Нет.Когда ты говоришь:
const char* c = "Hello World!";
Вы присваиваете c «ранее существовавшей» строковой константе, которая НЕ совпадает с:
char* c = new char[6];
Только в последнем случае вы выделяете память в куче.Итак, вы позвоните delete, когда закончите.
Я предполагаю, что когда я это сделаю
char* = "string"
это то же самое, чтоchar* = new char[6]
.
Нет.Первое, что делает, — это создает константу.Его изменение — неопределенное поведение.Но чтобы ответить на ваш вопрос;нет, вам не обязательно их уничтожать.И просто примечание: всегда используйте std::string
как только возможно.
Название игры: «Уничтожайте только то, что вы создали».Вот пары:
malloc
/free
calloc
/free
new
/delete
new []
/delete []
Поскольку вы создали вторую строку, используя new []
, на вас лежит ответственность уничтожить его с помощью delete []
.Вызов delete [] string2
когда вы закончите.
Теперь, если ваш код достаточно запутан и затрудняет отслеживание удалений, рассмотрите возможность использования указателей с ограниченной областью или автоматических указателей.А boost::scoped_ptr
класс из библиотеки boost — хорошее место для начала.Также загляните в РАИИ идиома, довольно удобная и полезная штука.
Они не одинаковы.Ваш первый пример представляет собой константную строку, поэтому она определенно не выделяется из кучи.Ваш второй пример — это выделение памяти во время выполнения из 6 символов, и это происходит из кучи.Вы не хотите удалять свой первый пример, но вам нужно delete []
ваш второй пример.
Вы не знаете, где хранятся строковые литералы.Это может быть даже постоянная память, поэтому ваш код должен выглядеть следующим образом:
const char* c = "string";
И новый массив символов должен быть удалитьd так же, как и любая другая динамически выделяемая область памяти.
new всегда является выделением, тогда как определение встроенной строки фактически встраивает данные в саму программу и не может быть изменено (некоторые компиляторы допускают это с помощью умного трюка, не беспокойтесь).
Некоторые компиляторы вводят встроенные строки, поэтому вы не можете изменить буфер.
char* const sz1 = "string"; // embedded string, immutable buffer
char* sz2 = new char[10]; // allocated string, should be deleted
Давайте посмотрим, что делает GCC 4.8 x86-64 Linux.
Программа:
#include <cstdio>
int main() {
const char *s = "abc";
char *sn = new char[4];
sn[3] = '\0';
std::printf("%s\n", s);
std::printf("%s\n", sn);
}
Компилируем и декомпилируем:
g++ -ggdb -std=c++98 a.cpp
objdump -CSr a.o
Вывод содержит:
const char *s = "abc";
8: 48 c7 45 f0 00 00 00 movq $0x0,-0x10(%rbp)
f: 00
c: R_X86_64_32S .rodata
char *sn = new char[4];
10: bf 04 00 00 00 mov $0x4,%edi
15: e8 00 00 00 00 callq 1a <main+0x1a>
16: R_X86_64_PC32 operator new[](unsigned long)-0x4
1a: 48 89 45 f8 mov %rax,-0x8(%rbp)
Интерпретация:
char *s = "abc"
переходит в.rodata
.Итак, вы не можетеfree
это никак.char *sn = new char[4];
происходит из выводаoperator new[]
.Поэтому вам следует освободить его, когда сможете.