C++14 auto关键字的改进
300 Words | Read in about 2 Min | View times
Overview
C++11对auto
关键字进行了重新定义,到了C++14又对auto
关键字做了进一步的改进。从C++14
开始,auto
关键字可以用于函数返回值推导和lambda表达式参数列表的类型推导了。本节内容就围绕这两项改进详细展开。
本系列文章将包括以下领域:
本章其他内容请见 《现代C++》
《C++ auto关键字》这篇文章介绍过关于C++11的auto
关键字特性的介绍。
函数返回值类型推导
基本用法
C++11是不允许将函数返回值类型声明为auto
的,会导致编译失败:
1#include <iostream>
2
3auto foo(int a) {
4 return a;
5}
6
7int main() {
8 auto ret = foo(1);
9 std::cout << "foo(1) = " << ret << std::endl;
10 return 0;
11}
使用C++11进行编译g++ -std=c++11 main.cpp -o main
将产生以下错误:
1main.cpp:3:1: error: ‘foo’ function uses ‘auto’ type specifier without trailing return type
2 3 | auto foo(int a) {
3 | ^~~~
4main.cpp:3:1: note: deduced return type only available with ‘-std=c++14’ or ‘-std=gnu++14’
改用C++14进行编译g++ -std=c++14 main.cpp -o main
就通过了。
auto
返回值还可以用于模板的函数返回值推导中:
1template<typename T>
2auto foo(T t) { return t; }
注意事项
- 返回值有多个分支,必须保证每个分支返回的类型可以进行隐式转化,否则编译失败
1auto foo(bool flag) {
2 return flag ? "hello" : 10; //error: operands to ‘?:’ have different types ‘const char*’ and ‘int’
3}
4
5auto bar(bool flag) {
6 return flag ? 3.14 : 10; //ok
7}
- 不能返回初始化列表
1auto baz() {
2 return {1, 2, 3}; //error: returning initializer list
3}
- 不能用于虚函数
1struct A {
2 virtual auto foo() { return 1; } //error: virtual function cannot have deduced return type
3};
- 用于递归函数中时,至少有一个退出路径返回具体类型
1auto fabonaci(int n) {
2 if (1 == n || 2 == n)
3 return 1;
4 return fabonaci(n - 1) + fabonaci(n - 2);
5}
lambda表达式参数列表类型推导
在《C++闭包》这篇文章中介绍了lambda表达式是作为闭包的一种实现方式。在C++11中lambda表达式的参数列表的类型是不能声明为auto
的,必须使用具体类型来声明。而在C++14,lambda表达式的参数列表类型已经可以通过auto
自动推导了:
1auto f = [](auto a) { return a; };
2std::cout << f(1) << std::endl; //auto推导为int
3std::cout << f(3.14) << std::endl; //auto推导为double