decltype vs auto
decltype vs auto
据我所知,decltype
和auto
都会试图弄清楚某种东西的类型
如果我们定义:
int foo () {
return 34;
}
那么这两种声明都是合法的:
auto x = foo();
cout << x << endl;
decltype(foo()) y = 13;
decltype(auto) y = 13; // alternatively, since C++14
cout << y << endl;
你能告诉我decltype
和auto
的主要区别吗?
decltype
给出传递给它的表达式的声明的类型。auto
执行与模板类型推导相同的操作。因此,例如,如果您有一个返回引用的函数,auto
仍然是一个值(您需要auto&
才能获得引用),但decltype
将恰好是返回值的类型。
#include <iostream>
int global{};
int& foo()
{
return global;
}
int main()
{
decltype(foo()) a = foo(); //a is an `int&`
// decltype(auto) a = foo(); alternatively, since C++14
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&`
// decltype(auto) c = foo(); alternatively, since C++14
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"
}
另请参阅David Rodríguez关于auto
或decltype
中只有一个可能的地方的回答。
这是C++11对C++11问题的回答
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
不能用于定义返回类型。
这是我对auto和decltype:的思考
两者在实践上最明显的区别是:
- 在expr的类型推导中,
decltype
推导出正确的类型(除了左值expr->左值ref),auto
默认为值
我们需要学习"数据流"模型,然后才能理解差异。
在我们的代码中,函数调用可以解析为数据流模型(类似于函数程序的概念),因此被调用的函数是数据接收器,调用方是<strong]数据提供者>。很明显,数据类型必须由数据接收器决定,否则数据无法在数据流中按顺序组织。
看这个:
template<typename T>
void foo(T t){
// do something.
}
无论您是否通过,T都将被推导为值类型。如果你想要ref类型,你应该使用auto&
或auto&&
,这就是我要说的,数据类型由数据接收器决定。
让我们回到auto
:
auto
用于对右值表达式进行类型推导,为数据接收器提供接收数据的正确接口。
auto a = some expr; // a is data receiver, and the expr is the provider.
那么为什么auto
会忽略ref修饰符呢?因为它应该由接收器决定。
为什么我们需要decltype
答案是:auto
不能用作真正的类型推导,它不会给你正确的表达式类型。它只是给数据接收器一个正确的类型来接收数据。
因此,我们需要decltype来获得正确的类型。
通常,如果需要初始化变量的类型,请使用autodecltype在需要非变量的类型(如返回类型)时更适合使用。
修改@Mankarse的示例代码,我认为一个更好的代码失败了:
#include <iostream>
int global = 0;
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 << "global: " << global << 'n'; //prints "global: 0"
std::cout << "---n";
//a is an `int&`
a = 10;
std::cout << "a: " << a << 'n'; //prints "a: 10"
std::cout << "b: " << b << 'n'; //prints "b: 2"
std::cout << "global: " << global << 'n'; //prints "global: 10"
return 0;
}
我认为auto是一个纯粹的简化功能,而decltype的主要目的是在基础库中实现复杂的元编程。然而,他们非常亲密从语言技术的使用角度来看是相关的。
来自HOPL20 4.2.1,Bjarne Stroustrup。
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- 如何为模板化对象创建模板向量?VS正在投掷C3203
- 数据成员SFINAE的C++17测试:gcc vs clang
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 正在VS调试器中监视映射条目
- Confusion: decltype vs std::function
- 将IBM Rhapsody模型集成到VS 2019中
- VS Code "command":"make"与终端窗口中的命令行"make"不同
- 使用VS Code和CMake Tools运行自定义命令
- 修改 VS Code 中的默认C++代码段
- 如何使用c++在VS 2019上运行SQL查询
- 在 VS Code 中编码时不能在 C++ 中使用 auto 关键字
- C++ Auto vs Auto&
- decltype vs auto
- 在 C++11 中使用 auto foo = "bar" vs std::string
- 在使用auto时初始化结构会导致VS 2013中的副本
- ' auto x = type{…} '初始化语法和'显式'转换操作符- clang vs gcc
- 无法在VS 14 CTP中使用auto声明lambda:类型为'void'的条件表达式是非法的
- c++ 11自动变量:float数组vs auto