Потому что char*
не является строкой. Это просто указатель на какой-то символ с условием, что за ним может следовать больше символов и что после последнего стоит '\0'
.
Строковый литерал в C (и, следовательно, в C++), такой как "abc"
, представляет собой просто массив символов, к которому компилятор молча добавляет '\0'
. Когда вы присваиваете массив указателю, массив автоматически преобразует указатель в первый элемент. Результат в том, что
at = "tw";
означает, что указателю at
назначается адрес первого символа в строковом литерале "tw"
. Тем самым он потеряет свою старую ценность. Поскольку это был адрес динамически выделяемого массива символов, вы пропускаете этот массив.
Когда вы позже присваиваете значение символу в массиве, на который сейчас указывает at
, вы присваиваете новое значение какому-то символу в строковом литерале. Это вызывает неопределенное поведение, и программа немедленно зависает или аварийно завершает работу, вероятно, лучшее, что может случиться с вами, когда вы это делаете. (На многих платформах вы записываете в постоянную память, делая это.)
Позже вы передаете at
в delete[]
(и не delete
, так как вы вызвали new[]
, а не new
). При этом вы передаете ему адрес строкового литерала вместо выделенного массива символов. Это, конечно, испортит работу диспетчера кучи. (Библиотека времени выполнения VC улавливает это в режиме отладки.)
std::strcpy
, с другой стороны, копирует строку символ за символом из одного массива в другой массив. Никакие указатели не будут изменены, копируются только участки памяти. Указатель на целевой массив после этого по-прежнему указывает на целевой массив, изменились только данные в этом массиве.
Позвольте мне добавить следующее: Если вы новичок в C++, вам следует использовать std::string
, а не строки C. Это делает за вас всю грязную работу и имеет разумную семантику.
person
sbi
schedule
16.10.2009
delete[]
- person MSalters   schedule 16.10.2009at = "tw";
, а затемat[2] = '\0';
является излишним."tw"
создает строковый литерал, который уже завершается нулем. Память для строки"tw"
выглядит как[ 't' | 'w' | '\0' ]
. Не только это, но иat[2] = '\0';
приведет к неопределенному поведению;"tw"
создает строковый литерал, который является строкой только для чтения, которая недоступна для записи, поэтому запись в этот строковый литерал только для чтения вызовет неопределенное поведение. Чтобы на самом деле назначить что-то таким образом, вам нужно будет сделатьconst char *at = "tw";
, который создаст строковый литерал, аat
укажет на то же место. - person RastaJedi   schedule 18.04.2016