Авто со строковыми литералами
#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]
Ответы
Ответ 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)...