Подтвердить что ты не робот

Почему строковый литерал неявно преобразуется в 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") ОК?

4b9b3361

Ответ 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 *.