Почему строковый литерал неявно преобразуется в char * только в определенном случае?
void f(char* p)
{}
int main()
{
f("Hello"); // OK
auto p = "Hello";
f(p); // error C2664: 'void f(char *)' : cannot convert parameter 1
// from 'const char *' to 'char *'
}
Код был скомпилирован с VС++ Nov 2012 CTP.
§2.14.15 Строковые литералы, раздел 7
Узкий строковый литерал имеет тип "массив из n const char", где n размер строки, как определено ниже, и имеет статическое хранилище длительность.
Почему f("Hello")
ОК?
Ответы
Ответ 1
Это поведение отличается от C и С++, по крайней мере теоретически.
В C: строковый литерал распадается на неконстантный указатель. Однако это не делает его хорошей идеей; попытка изменить строку через этот указатель приводит к поведению undefined.
В С++: он никогда не работает (AFAIK). * Однако некоторые компиляторы могут все же позволить вам с этим справиться. Например, GCC имеет флаг -Wwrite-strings
, который включен по умолчанию (по крайней мере, в версии 4.5.1 и далее).
* В С++ 11, по крайней мере. (У меня нет более старых спецификаций.)
Ответ 2
f("Hello");
Даже это не нормально в С++. Компилятор должен дать диагностику, иначе он должен быть обновлен.
В С++ "Hello"
конвертируется в const char*
, а не char*
.
Преобразование из "Hello"
в char*
разрешено в С++ 03, хотя оно устарело. И в С++ 11 преобразование недопустимо, а код плохо сформирован.
Ответ 3
Разница между
f("Hello");
и
f(p);
заключается в том, что первое включает в себя литерал. В С++ 03 было поддержано преобразование из строкового литерала в char*
(примечание: not const
). Он больше не поддерживается в С++ 11, но мало, если какие-либо компиляторы еще не достигли этого изменения правила.
Ответ 4
Я думаю, потому что авто ключевое слово. он выводит вывод, поэтому компилятор не знает, как его преобразовать в char *.