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

Авто со строковыми литералами

#include <iostream>
#include <typeinfo>

int main()
{
    const char a[] = "hello world";
    const char * p = "hello world";
    auto x = "hello world";

    if (typeid(x) == typeid(a))
        std::cout << "It an array!\n";

    else if (typeid(x) == typeid(p))
        std::cout << "It a pointer!\n";   // this is printed

    else
        std::cout << "It Superman!\n";
}

Почему x выводится как указатель, когда строковые литералы являются фактически массивами?

Узкий строковый литерал имеет тип "array of n const char" [2.14.5 Строковые литералы [lex.string] §8]

4b9b3361

Ответ 1

Функция auto основана на выводе аргумента шаблона, а вывод аргумента шаблона ведет себя аналогично, в частности, согласно §14.8.2.1/2 (стандарт С++ 11):

  • Если P не является ссылочным типом
    • Если A является типом массива, тип указателя, созданный преобразованием от массива к указателю, используется вместо A для вывода типа

Если вы хотите, чтобы тип выражения x был типом массива, просто добавьте & после auto:

auto& x = "Hello world!";

Затем заполнитель auto будет выведен как const char[13]. Это также похоже на шаблоны функций, принимающих ссылку в качестве параметра. Просто чтобы избежать путаницы: объявленный тип x будет ссылкой на массив.

Ответ 2

Почему x выведено как указатель, когда строковые литералы являются фактически массивами?

Из-за преобразования массива в указатель.

Если x следует выводить как массив, только если разрешено следующее:

const char m[]          = "ABC";

const char n[sizeof(m)] = m; //error

В С++ атрибут не может быть инициализирован другим массивом (например, выше). В таких случаях исходный массив распадается на тип указателя, и вы можете сделать это вместо этого:

const char* n = m; //ok

Правила для вывода типа с auto аналогичны правилам вывода типа в шаблоне функции:

template<typename T>
void f(T n);

f(m);     //T is deduced as const char*
f("ABC"); //T is deduced as const char*

auto n = m;     //n type is inferred as const char*
auto n = "ABC"; //n type is inferred as const char*

В §7.1.6.4/6 говорится о спецификаторе auto:

Тип, выведенный для переменной d, тогда выведенный A определяется с использованием правил вывода аргумента шаблона из вызова функции (14.8.2.1)...