Decltype vs auto
Как я понимаю, оба decltype
и auto
будут пытаться выяснить, что это за тип.
Если мы определим:
int foo () {
return 34;
}
Затем оба объявления являются законными:
auto x = foo();
cout << x << endl;
decltype(foo()) y = 13;
cout << y << endl;
Не могли бы вы рассказать мне, каково главное различие между decltype
и auto
?
Ответы
Ответ 1
decltype
дает объявленный тип передаваемого ему выражения. auto
делает то же самое, что и вычет типа шаблона. Например, если у вас есть функция, возвращающая ссылку, auto
все равно будет значением (вам нужно auto&
, чтобы получить ссылку), но decltype
будет точно типом возвращаемого значения.
#include <iostream>
int global{};
int& foo()
{
return global;
}
int main()
{
decltype(foo()) a = foo(); //a is an `int&`
auto b = foo(); //b is an `int`
b = 2;
std::cout << "a: " << a << '\n'; //prints "a: 0"
std::cout << "b: " << b << '\n'; //prints "b: 2"
std::cout << "---\n";
decltype(foo()) c = foo(); //c is an `int&`
c = 10;
std::cout << "a: " << a << '\n'; //prints "a: 10"
std::cout << "b: " << b << '\n'; //prints "b: 2"
std::cout << "c: " << c << '\n'; //prints "c: 10"
}
Также см. ответ Дэвида Родригеса о местах, в которых возможны только один из auto
или decltype
.
Ответ 2
auto
(в контексте, где он указывает тип) ограничивается определением типа переменной, для которой существует инициализатор. decltype
- это более широкая конструкция, которая за счет дополнительной информации выведет тип выражения.
В случаях, когда auto
может использоваться, он более краткий, чем decltype
, так как вам не нужно предоставлять выражение, из которого будет выведен тип.
auto x = foo(); // more concise than `decltype(foo()) x`
std::vector<decltype(foo())> v{ foo() }; // cannot use `auto`
Ключевое слово auto
также используется в полностью несвязанном контексте при использовании возвращающих возвращаемых типов для функций:
auto foo() -> int;
Там auto
является только лидером, так что компилятор знает, что это объявление с возвращаемым типом возврата. Хотя приведенный выше пример может быть тривиально преобразован в старый стиль, в общем программировании полезно:
template <typename T, typename U>
auto sum( T t, U u ) -> decltype(t+u)
Обратите внимание, что в этом случае auto
не может использоваться для определения типа возврата.
Ответ 3
Как правило, если вам нужен тип переменной, которую вы собираетесь инициализировать, используйте авто. decltype лучше использовать, когда вам нужен тип для чего-то, что не является переменной, типа возвращаемого типа.