auto (C++)

✍ dations ◷ 2024-09-20 10:31:24 #C++

auto是C++程序设计语言的关键字。自C++11以来,auto关键字用于两种情况:声明变量时根据初始化表达式自动推断该变量的类型、声明函数时函数返回值的占位符。C++98标准中auto关键字用于自动变量的声明,但由于使用极少且多余,在C++11中已删除这一用法。

auto可以在声明变量时根据变量初始值的类型自动为此变量选择匹配的类型。C++语言类似的关键字还有decltype。

举例:对于值x=1;即可以声明:int x = 1或long x = 1,也可以直接声明auto x = 1。

其它语言的类似功能包括C#的var关键字。

根据初始化表达式自动推断被声明的变量的类型,如:

 auto f=3.14;      //double auto s("hello");  //const char* auto z = new auto(9); // int* auto x1 = 5, x2 = 5.0, x3='r';//错误,必须是初始化为同一类型

但是,这么简单的变量声明类型,不建议用auto关键字,而是应更清晰地直接写出其类型。

auto关键字更适用于类型冗长复杂、变量使用范围专一时,使程序更清晰易读:

 std::vector<int> vect;  for(auto it = vect.begin(); it != vect.end(); ++it) {  //it的类型是std::vector<int>::iterator    std::cin >> *it;  }

或者保存lambda表达式类型的变量声明:

  auto ptr = (double x){return x*x;};//类型为std::function<double(double)>函数对象

在模板函数定义时,如果变量的类型依赖于模板参数,使用auto关键字使得在编译期确定这些类型,如:

 template <class T, class U>void Multiply(T t, U u) {      auto v = t * u;      std::cout<<v; }

模板函数的返回类型如果也是依赖于从模板参数推导,

 template <typename _Tx, typename _Ty> auto multiply(_Tx v1, _Ty v2) -> decltype( _Tx * _Ty ) {     return v1*v2; } auto result = multiply(101, 1.414); // 结果类型是double

语义

使用auto关键字做类型自动推导时,依次施加以下规则:

这一组规则同于模板函数的模板参数推导(template argument deduction)时的规则。但auto关键字可以从C++11风格的花括号{与}包围的值列表推导出std::initializer_list;而模板函数的形参推导时不认为这种值列表是一个类型,因此不能由值列表推导出std::initializer_list类型。

因而,使用auto关键字声明变量的类型,不能自动推导出顶层的CV-qualifiers,也不能自动推导出引用类型,需要显式指定。例如:

   const int v1 = 101;   auto v2 = v1;       // v2类型是int,脱去初始化表达式的顶层const   v2=102;            // 可赋值   auto al = { 10, 11, 12 };//类型是std::initializer_list<int>   template<class T> void foo(T arg); // 函数模板声明   foo(v2); //函数模板实例化为 void foo<int>(int)

如果需要具有顶层的CV-qualifiers,或者引用的类型,解决办法是显式指明:

   const auto& v3=v1;   foo<const int&>(v1);//直接指明模板参数类型   template<class T> void foo(const T& arg);//或者偏特化模板函数

如果auto关键字还带上&号,声明引用类型,则不执行const剥除(const-stripping),例如:

   const int c = 0;   auto& rc = c;   rc = 44; // 编译错误,const int类型

这是因为如果不抑制const剥除,则得到了一个非常量引用型变量,指向了const变量,这显然是不可接受的。模板参数推导也遵循此规则。

初始化表达式为数组,auto关键字推导的类型为指针。这是因为数组名在初始化表达式中自动隐式转换为首元素地址的右值。例如:

   int a;   auto j = a;   std::cout << typeid(j).name() << " "<<sizeof(j)<<" "<<sizeof(a)<< std::endl;

由于C++规定字符串字面量是左值,因此可以通过&运算符直接取地址:

   auto al = &"hello";  // a1的类型是const char(*)   

auto关键字的类型完美转发

C++11使用auto声明变量时,如:auto&& var=initValue;“auto&&”并不意味着这一定是右值引用类型的变量,而是类似于模板函数参数的类型推导,既可能是左值引用,也可能是右值引用。其目的是把初始化表达式的值分类情况,完美转发给由auto声明的变量。也即:

相关

  • 天王补心丸天王补心丹是中医药学传统方剂。同名方约有9首。《校注妇人良方》卷六:人参(去芦)、玄参、丹参、茯苓、远志、桔梗各五钱,生地黄四两,当归酒浸、五味、天门冬、麦门冬去心、柏子
  • 克吕尼修道院克吕尼修道院(法语:abbaye de Cluny),公元910年由阿基坦公爵虔诚者威廉在法国勃艮第索恩-卢瓦尔省克吕尼(英语:cluny)建立的天主教修道院。克吕尼修道院发起了天主教改革运动克吕尼
  • 导引导引是一项以肢体运动为主,配合呼吸吐纳的养生方式,源于上古的舞蹈动作。春秋战国时期,导引术获得长足的发展,出现了“熊经”、“鸟伸”等术势。马王堆三号汉墓出土《导引图》的
  • 伯罗奔尼撒战争伯罗奔尼撒战争是以雅典为首的提洛同盟与以斯巴达为首的伯罗奔尼撒联盟之间的一场战争。这场战争从前431年一直持续到前404年,期间双方曾几度停战,最终斯巴达获得胜利。这场战
  • 日苏国界战争苏日边界冲突是指从1938年—1945年间,苏联与日本之间的一系列边界冲突。在占领满洲国及朝鲜半岛后,日本转而有意夺取对苏联领土,日本皇军与苏联红军因而在中国东北频繁地爆发冲
  • 耀龙耀龙属(属名:Epidexipteryx,意为“炫燿的羽毛”)是种小型手盗龙类恐龙,化石发现于中国内蒙古宁城县的道虎沟化石层,年代为侏罗纪中期或晚期,约1亿6800万到1亿5200万年前。耀龙的化
  • 礁溪乡礁溪乡(台湾话:.mw-parser-output .sans-serif{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Lato,"Helvetica Neue",Helvetica,Arial,sans-serif} Ta-kh
  • 情侣爱人,在中国大陆通常用来作为夫妻之间的称呼,在台湾泛指第三者不伦恋人意味,爱人则常用称呼交往中情侣。爱人在中国大陆曾是专用于对婚姻配偶的称呼,对人的爱情亲密对像,为未婚恋
  • 威廉·斯坦利·杰文斯威廉姆·斯坦利·杰文斯(William Stanley Jevons,1835年9月1日--1882年8月13日),生于利物浦,英国著名的经济学家和逻辑学家。他在著作《政治经济学理论》(1871年)中提出了价值的边
  • 锂 (药物)锂盐(英语:Lithium salts)为含锂离子的离子化合物,临床上通常指碳酸锂。锂盐在医学上可作为一种精神科药物,用于躁郁症与其他抗忧郁药治疗无效的重性抑郁障碍。锂能够降低这些疾