2012-03-25 3 views
1

Это безопасно сделать что-то вроде этого:Играя с массив символов

char* charArray = new char[10]; 
strcat(charArray, "qwertyuiop"); 
charArray[3] = '\0'; 
delete [] charArray; 

Будет ли все быть удалены? Или что после \0 не будет? Я не знаю, оставил ли я мусор.

EDIT: должно быть strcpy

+0

Сделайте ссылку charArray [20] и увидите это значение после удаления [] – gaussblurinc

+3

Вызов strcat приведет к Undefined Behavior - после этого все ставки будут отключены. –

+1

Paul R ссылается на то, что неизвестно, где первый '\ 0' находится в памяти, где указывает charArray, поскольку функциональность strcat зависит от ее обнаружения. – Eric

ответ

5

Если вы хотите написать strcpy вместо strcat, то, что является безопасным и правильным. Но, похоже, у вас есть неправильное представление о delete [] charArray. Он не удаляет символы, он удаляет память, на которую указывает charArray. В памяти даже после delete [] charArrayможет содержать эти символы, но это не гарантировано.

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

+1

Это должно быть 'strcpy' - typo. – user1112008

+0

'strcat()' в неинициализированном массиве конечно ** не ** отлично. –

+1

@dasblinkenlight: встроенные типы не инициализируются. Если вы хотите его инициализировать, вы должны написать 'new char [N]()'. Обратите внимание на '()' в новом выражении. – Nawaz

2

Нет, это прекрасно, весь массив удален. delete не смотрит на то, на что указывает указатель, на который вы указываете. Если вы согласитесь с new с delete и new[] с delete[], то необходимый объем памяти будет освобожден.

(Но не рекомендуется использовать std::string вместо символьных массивов, которые будут избежать много ошибок, как тот, который вы там пишете мимо конца вашего массива.)

7

Помимо того, что new[] для POD -types не нуль инициализирует массив, и strcat записывает завершающий '\0' за конец выделенной области, все выглядит нормально: в частности, delete удалит весь блок.

Причина для записи за конец выделенного блока заключается в том, что для 10-символьной строки "qwertyuiop" требуется 11 байтов для хранения.

+0

'charArray' не инициализируется. 'strcat' добавит слово к мусору и, вероятно, перепишет больше, чем только один байт. Поведение не определено. – bames53

+0

Объекты инициализируются по умолчанию, но для примитивных типов, которые не означают нулевой инициализации. См. [Dcl.init] 8.5/6. Применимый случай - «никакая инициализация не выполняется». – bames53

+0

@ bames53 Очень интересно! Я перечитываю спецификацию, и похоже, что типы POD не инициализируются по умолчанию в 'new []'. Я отредактировал ответ, чтобы отразить его, спасибо. – dasblinkenlight

2

Оператор delete[] ничего не знает о том, что хранится в буфере (в том числе, является ли оно строкой или нет), поэтому он удалит все 10 символов. Однако ваш вызов strcat переполняет конец массива (поскольку строки C имеют нулевой байт в качестве терминатора), что может сломать удаление на вашей платформе и вообще небезопасно.

3

delete[] освобождает память, выделенную после уничтожения объектов внутри (что ничего не делает для char). Он не заботится о содержимом, то есть освобождает столько объектов, сколько было выделено.

Обратите внимание, что использование strcat() зависит от нулевого символа, чтобы найти конец строки и что память, возвращаемая с new char[n], неинициализирована. Вы хотите, чтобы начать вместе с

*charArray = 0; 

... и вы могли бы хотеть рассмотреть strncat() или, еще лучше, не использовать это вообще, а использовать std::string.

+0

+1 для обсуждения (de) выделения вместо удаления (что более точно, несмотря на имя оператора) и упоминания 'std :: string', вы программируете C++ в конце концов. :-) – Eric

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