C++ 中的 auto的用法
auto的原理就是根据后面的值,来自己推测前面的类型是什么。
auto的作用就是为了简化变量初始化,如果这个变量有一个很长很长的初始化类型,就可以用auto代替。
1.用auto声明的变量必须初始化(auto是根据后面的值来推测这个变量的类型,如果后面没有值,自然会报错)
2.函数和模板参数不能被声明为auto(原因同上)
3.因为auto是一个占位符,并不是一个他自己的类型,因此不能用于类型转换或其他一些操作,如sizeof和typeid
4.定义在一个auto序列的变量必须始终推导成同一类型
示例:
std::vector<std::string> ve; std::vector<std::string>::iterator it = ve.begin();
我们可以用atuo来代替那个初始化类型:
auto it = ve.begin();
此外,如果是可用迭代器的对象的话,还可以这样操作:
int main(){ vector<int>v; v.push_back(1); v.push_back(2); v.push_back(3); for(auto i : v){ cout<<i<<" "; } cout<<endl; return 0; }
auto在这里就是简单的替换了int类型
函数返回值中的 auto
C++11
C++11 中引入了一个新的关键字 auto
, 用于自动型别推导. 同时引入了一个新的写法.
auto func(T parameters) -> type;
把函数返回类型写在后面, 这叫做 trailing return type. 这个写法等价于把 type 放在前面的通常函数, 比如
type func(T parameters);
所以说 auto
关键字只是一个占位符, 不过配合上同为 C++11 引入的 decltype
关键字, 就可以进行类型推导. 比如下面这个模板函数
template <typename U, typename V>
auto add(U a, V b) -> decltype(a + b);
// add(float, double) 返回 double
// add(float, int) 返回 float
// 诸如此类
这样可以通过 a + b
的型别推断出 add
函数的返回类型. 这样的话, 返回的型别就可以利用函数参数的型别所决定了.
C++14
新的占位符 auto
C++14 允许你在函数定义的时候, 使用真正的 auto
, 如果在一个函数定义的时候用上 auto
, 那他就会按照下面这个方式推断.
auto func(T parameters){
return something;
}
这个 auto 推导的结果就相当于
auto value = something;
之中的 auto 所推导的结果. 类似地, auto &
, auto &&
, const auto
, const auto &
等关键字也都是这个原理.
这些关键字使用上是有区别的, 比如 auto &
只能返回左值引用, 而 auto &&
既能返回左值引用, 又能返回右值引用. auto
只能返回一个型别. 等等.
这样子的写法只能在函数定义中使用, 因为必须同时提供返回值才能完成推导.
老的占位符 auto
C++14 为 C++11 中这种写法
auto func(T parameter) -> decltype(something) // decltype() 中就是返回值
{
return something;
}
留了个简化的写法:
decltype(auto) func(T parameter)
{
return something;
}
同样我们需要给出函数的 definition, 而不只是 declaration.
这就是常用的 decltype(auto)
的含义了.
decltype
的推导规则和 auto
, auto &
, auto &&
, const auto
, const auto &
等都不一样. 它既可以返回类型, 又可以返回左右值引用, 还会保留 const
语义, 挺不一样的.
用在 lambda 中
定义一个典型的 lambda 实际上需要
- 捕获 [],
- 函数参数 (),
- 返回类型
type
, - 函数定义 {}.
auto f = []() -> type {};
这里我们省略了一些关键字, 比如 mutable
, noexcept
等. C++17 中还可以用 constexpr
等关键字.
当然这个 -> type
也可以不写. 不写就意味着被 C++14 中的 -> auto
占位了. 包括 C++11 也是这样的, 尽管 C++11 中还没有 auto
的这个用法.
函数参数的 auto
我们刚刚说的都是返回类型的地方放一个 auto
. 我们下面来聊聊函数参数中的 auto
.
lambda 参数中的 auto
C++ 14 中允许了 lambda 参数使用 auto
, auto &&
等等 C++14 的类型占位符. 你可以写出这样的代码:
auto sum = [](auto x, auto y) { return x + y; };
sum
就有点像模板了, 遇到的时候会自行推断 x + y
的型别. 尽管如此, 你仍然不能写一个具有函数模板形式的 lambda.
普通函数中的 auto
我们知道长期以来, C++ 有函数模板, 而 lambda 的参数可以用 auto 变得像函数模板一样. 这两个东西这么像, 终于在 C++20 中得到了统一.
在 C++20 中, 我们在函数参数中也可以用 auto
, auto &
, auto &&
等等之一了. 而在 lambda 中, 我们也可以使用显式的模板参数列表了. 你可以写出:
auto add(auto x, auto y)
{
return x + y;
}
这种很奇怪的代码了.
也可以写出
auto add = []<typename T, typename S>(T x, S y) { return x + y; };
这种很长的代码了.
修改于2022.11.8//14:58:46
auto、auto&、auto&&、const auto和const auto&的区别:
for(auto x : vector)
auto会拷贝一份容器内的vector,在修改x时不会改变原容器当中的vector值,只会改变拷贝的vector。
因为拷贝发生在编译期间,所以并不会对运行速率造成很大影响。
for(auto& x : vector)
当需要对原数据进行同步修改时,就需要添加&,即vector的引用。
会在改变x的同时修改vector。
for(auto&& x : vector)
当vector返回临时对象,使用auto&会编译错误,临时对象不能绑在non-const l-value reference (左值引用)需使用auto&&,初始化右值时也可捕获
for(const auto& x : vector)
const (常类型),不能作为左值
& (引用),不拷贝,不申请新空间,会对原vector修改
当我们不希望拷贝原vector(拷贝需要申请新的空间),同时不愿意随意改变原vector,那么我们可以使用for(const auto& x : vector),这样我们可以很方便的在不拷贝的情况下读取vector,同时不会修改vector。一般用在只读操作。
const auto x : vector
该操作相对于const auto& x : vector只是少了引用(&),即会申请新的空间(拷贝),不经常使用。
转载于
本文来自博客园,作者:slowlydance2me,转载请注明原文链接:https://www.cnblogs.com/slowlydance2me/p/16847707.html