C++简单笔记 - auto关键字_c++ auto_杰里米21的博客-程序员宅基地

技术标签: 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关键字做类型自动推导时,依次施加以下规则:[参 1]

  • 首先,如果初始化表达式是引用,首先去除引用;
  • 上一步后,如果剩下的初始化表达式有顶层的const且/或volatile限定符,去除掉。

这一组规则同于模板函数的模板参数推导(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[9];
auto j = a;
std::cout << typeid(j).name() << " "<<sizeof(j)<<" "<<sizeof(a)<< std::endl

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

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

auto关键字的类型完美转发

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

  • 如果初始化值(initializer)是类型A的左值,则声明的变量类型为左值引用A&;
  • 如果初始化值是类型A的右值,则声明的变量类型为右值引用A&&。
#include<iostream>  
#include <vector>
#include <typeinfo>
using namespace std;
 
struct Widget{
    };
Widget makeWidget(){
     return Widget(); } // 类工厂函数

int main()
{
    
	Widget&& var1 = Widget(); // var1的类型是右值引用,但是作为左值
	auto&& var2 = var1;       //var2的类型是左值引用
	std::vector<int> v = {
     1, 2, 3 };
	auto&& val = v[0]; // std::vector::operator[]的返回值是元素左值,所以val的类型是左值引用
	Widget&& var3 = makeWidget(); // var3是左值,但它的类型是右值引用 
	Widget var4 = static_cast<Widget&&>(var1); // var4是左值,但它的类型是右值引用

	std::cout << typeid(var1).name() << std::endl;
	std::cout << typeid(var2).name() << std::endl;
	std::cout << typeid(val).name() << std::endl;
	std::cout << typeid(var3).name()  << std::endl;
	std::cout << typeid(var4).name() << std::endl;
}

参考文献

  1. C++ auto and decltype Explained, by Thomas Becker
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_50470102/article/details/123231798

智能推荐

前端程序员一般在哪些网站接单?_前端开发接单平台_程序员小范的博客-程序员宅基地

之前也写过一期前端程序员兼职接单的方法,但有粉丝私信说文章中前端接单的网站是比较少的,对想要找更多的网站对比下,今天就给大家做一个补充,希望能够帮到有需要的同学哦~_前端开发接单平台

Scratch3.0创意编程(基础篇):第11课 智能小车_scratch3.0编程基础课程11-程序员宅基地

前言本节课程序逻辑性不强,重点是让学生了解角色之间的层级关系,并且学习通过积木指令调整层级关系。本节课归纳了角色不显示时的常见几种情况,并总结了解决方法。课程目标1、学习角色之间的层级关系。2、学习通过侦测模块检测角色之间的距离。3、学习角色不显示时常见的解决方法。程序效果程序分析编程知识课后小题欢迎大家多多提建议~~..._scratch3.0编程基础课程11

算数运算符重载:__add__ 、 __radd__ 、 __iadd__为例-程序员宅基地

__add__表示‘左加’,若对象在+右边则会报错TypeErrorclass Number: def __init__(self, num): self.num = num def __str__(self): return str(self.num) # 对象出现在'+'的左边时自动触发 def _...___radd__

c++ 隐藏理解_c++ hidden-程序员宅基地

在面向对象的开发过程中,经常出现类的继承,这里面出现的成员函数的重载(overload)、覆盖(override)与隐藏(hidden)很容易混淆。首先澄清这3个概念1. 重载1)发生在同类中;2)函数名相同;3)参数不同;4)可加可不加virtural关键字2. 重写(覆盖)1)发生在父类与子类中;2)函数名相同;3)参数相同;4)必须加virtural关键字3. 隐藏..._c++ hidden

面向对象——抽象类和接口(笔记)_面向对象抽象类和接口_江夬的博客-程序员宅基地

抽象类抽象类快速入门抽象类的介绍抽象类使用的注意事项和细节讨论public class test { public static void main(String[] args) { //抽象类,不能被实例化// new A();//报错 }}//抽象类不一定要包含abstract方法。也就是说,抽象类可以没有abstract方法//,还可以有实现的方法。abstract class A { public void hi(_面向对象抽象类和接口

花窗图案C语言编程,观赏故宫仿花窗图案的意义,仿花窗图案寓意_黑猫厨房的博客-程序员宅基地

太和殿、景仁宫、临溪亭及其乾清门是北京故宫中仿古式花窗较为具备特点的好多个殿室,且每个花图案各是说道,下边人们就而言说北京故宫中,这到处花窗的花图案及其喻意。一、太和殿:三交六椀款式,三交六椀菱花款式花图案,代表正统的國家政党,内函乾坤,喻意八方,是喻意乾坤之交而生天地万物的这种标记。这类花图案是用直棂与斜棂交点后构成若干意见的等边三角形,三边形交点独到之处便变成一枝六瓣菱花,三边形正中间成环形。...

随便推点

ctf web方向与php学习记录11之sql初见_ctfweb方向sql-程序员宅基地

初见:SQL即结构化查询语言(Structured Query Language),是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。SQL语句无论是种类还是数量都是繁多的,很多语句也是经常要用到的,SQL查询语句就是一个典型的例子,无论是高级查询还是低级查询,SQL查询语句的需求是最频繁的。学习1数据库定义:数据库是按照数据结构来组织、存储和管理数据的仓库。2sql注入的定义:SQL是操作数据库数据的结构化查询语_ctfweb方向sql

数据结构之单链表实验_单链表实验内容_lannnn_的博客-程序员宅基地

单链表实验实验目的实验环境实验要求实验内容源代码运行结果实验目的掌握线性表的定义、特点、逻辑结构,理解线性表的抽象数据类型。熟练掌握线性表的两种存储结构的结构类型定义、特点和基本操作的实现。通过本次实验帮助学生加深对线性表的理解,并加以应用;实验环境CodeBlocks实验要求1.熟悉c语言的语法知识;2.了解线性表的逻辑结构特性;3.掌握线性表的链式存储结构—单链表的定义、创建、插入、删除、取值等基本操作;实验内容完成单链表的基本操作(定义、初始化、插入、删除、定位等)的汇总,_单链表实验内容

android底部导航进行跳转,Android实现底部导航菜单的跳转--BottomNavigationView-程序员宅基地

效果: 项目结构: 需要用到design依赖: 现在是:implementation ‘com.android.support:design:28.0.0’代码:activity_main.xmlmy_fragment.xml(其他两个类似不在累述)home_bottom_tab_color_selsctor.xmlhome_bottom_tab_my_selector.xmlMainActi...

Archlinux下wordpress本地安装 &&Archlinux下lampp环境配置..-程序员宅基地

Archlinux下wordpress本地安装&&Archlinux下lampp环境配置.. 标题虽然是wordpress的本地安装,,其实虚晃一枪,讲讲lampp的配置.. 本来这种类型的文章是要发到lifeintheweb上的..但是现在校园网到期了..不知道为什么可能是因为用了路由吧..现在外网进不去我网站的控制板,写不了博..很YM明天果断去给校园网交钱...暂且发到这里吧.. windows下本地安装wordpress非常简单..只需要安装一个wamp就可以了..linux下原来我是自己手

一个交互比较复杂的页面(1新增)-程序员宅基地

新增jsp:<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><%@ taglib prefix="fmt"...

黑苹果的安装步骤-程序员宅基地

时隔半年,再一次回到黑苹果的圈里,还记得第一次装黑苹果是用虚拟机装的,当时跟着网上的教程,一步一步的装,当时毕竟是用的虚拟机,装好后的Mac系统简直就跟屎一样,让人作呕,后来,在半年前,自己狠下心,用真机装了一把,装真机和用虚拟机差别还是很大的,需要找和自己电脑品牌相对应的clover,这个clover我的理解是引导启动系统的,我是爬了好多楼,加了好多群,找资源,找教程,熬了很久才...