zoukankan      html  css  js  c++  java
  • auto类型-现代C++新特性

    auto类型

    C++11中引入的auto主要用于类型推导。auto在C++98中“存储类型指示符”的语义,由于使用极少且多余,该语义从C++11开始被删除。

    auto类型推导用于从初始化表达式中推断出变量的数据类型,通过此方法可以有效简化代码:

    Example:

    //简化前的代码
    
    for (std::vector<std::string>::iterator i = vs.begin(); i != vs.end(); i++)
    {
    	//code
    }
    
    
    //简化后的代码
    
    for (auto i = vs.begin(); i != vs.end(); i++)
    {
    	//code
    }
    

    上例中,auto能够自动推导出vs.begin()的类型,从而避免了冗长的类型说明。这个用法是我们大力推荐的。


    当auto用于模板定义中,其“自适应”性会得到更充分的体现。

    Example:

    #include<iostream>
    
    template<typename T1, typename T2>
    double Sum(T1 & t1, T2 & t2)  //从c++14起,也可以支持函数返回值类型设为auto,这种用法多用于编写库的开发人员。
    {
    	auto s = t1 + t2;	//s的类型会在模板实例化时被推导出来
    	return s;
    }
    
    int main()
    {
    	int a = 3;
    	long b = 5;
    	float c = 1.0f, d = 2.3f;
    
    	auto e = Sum<int, long>(a, b);		//s的类型被推导为long
    	auto f = Sum<float, float>(c, d);	//s的类型被推导为float
    	std::cout << e << "  " << f << std::endl;
    	
    	return 0;
    }
    
    //编译选项:g++ -std=c++11  auto1.cpp
    

    上例中,由于类型T1、T2要在模板实例化时才能确定,所以在Sum中将变量s的类型声明为auto。


    auto可以与指针和引用结合起来使用,使用效果符合我们的想象。如下例所示:

    Example:

    #include<iostream>
    #include<typeinfo>
    
    int main()
    {
    	int x = 0;
    	int *y = &x;
    
    	auto &b = x;			//int&
    	auto c = y;			    //int*
    	auto *d = y;			//int*
    	auto e = b;				//int
    
    	return 0;
    }
    
    //编译选项:g++ -std=c++11  auto2.cpp
    

    本例中,对于c、d两个变量而言,声明其为auto*或auto并没有区别。

    而如果要使得auto声明的变量是另一个变量的引用,则必须使用auto&,如本例中的变量b。而本例中e没有带&,则被推导成int类型。正如我们所熟知的,使用引用其实是使用引用的对象,特别是当引用被用作初始值时,真正参与初始化的其实是引用对象的值。


    其次,auto与const和volatile之间也存在着一些相互关系。const和volatile代表了变量的两种不同的属性:易失和常量。在c++标准中,它们常常被一起叫作cv限制符(cv-qualifier)。

    在深入介绍auto和cv限定符连用之前,先介绍下C++11中的顶层const和底层const。顶层const(top-level const)表示指针本身是一个常量,而底层const(low-level const)表示指针所指的对象是一个常量。

    更一般的,顶层const可以表示任意的对象是常量,这一点对于任何数据类型都适用,如算术类型、类、指针等。底层const则与指针和引用等复合类型的基本类型部分有关。

    int i = 0;
    int *const p1 = &i;			//顶层const
    const int ci = 42;			//顶层const
    const int *p2 = &ci;		//底层const
    const int *const p3 = p2;	//右边的const是顶层const,左边的const是底层const
    const int &r = ci;			//用于声明引用的const都是底层const
    

    同理,volatile与const的用法相似。


    鉴于cv限制符的特殊性,C++11标准规定auto可以与cv限制符一起使用。在连用时,auto一般会忽略掉顶层const,同时底层const则会保留下来,比如当初始值时一个指向常量的指针时:

    Example:

    int i = 0;
    const int ci = i, &cr = ci;
    auto b = ci;	//b:int(ci的顶层const特性被忽略掉了)
    auto c = cr;	//c:int(cr是ci的别名,ci本身是顶层const)
    auto d = &i;	//d:int *(整数的地址就是指向整数的指针)
    auto e = &ci;	//e:const int *(对常量对象取地址是一种底层const)
    

    如果希望推断出auto类型是一个顶层const,需要明确指出:

    const auto f = ci; //ci的推演类型是int,f是const int
    

    同理volatile与auto连用的用法和const一致。


    auto在使用上的限制:以下四种情况特点基本类似,人为观察很容易能够推导出auto所在位置应有的类型,但现有标准还不支持这样的方式。

    Example:

    #include<vector>
    using namespace std;
    
    void fun(auto x = 1)		//1:auto函数形参,无法通过编译
    {}
    
    struct str
    {
    	auto var = 10;			//2:auto非静态成员变量,无法通过编译
    };
    
    int main()
    {
    	char x[3];
    	auto y = x;
    	auto z[3] = x;			//3:auto数组,无法通过编译
    
    	vector<auto> v = { 1 };	//4.auto模板参数(实例化时,)无法通过编译
    	return 0;
    }
    
    //编译选项:g++ -std=c++11  auto3.cpp
    
    新战场:https://blog.csdn.net/Stephen___Qin
  • 相关阅读:
    10. Regular Expression Matching
    9. Palindrome Number (考虑负数的情况)
    8. String to Integer (整数的溢出)
    7. Reverse Integer (整数的溢出)
    LeetCode Minimum Size Subarray Sum
    LeetCode Course Schedule II
    Linux 文件缓存 (一)
    LeetCode Tries Prefix Tree
    Linux : lsof 命令
    LeetCode Binary Tree Right Side View
  • 原文地址:https://www.cnblogs.com/Stephen-Qin/p/9387891.html
Copyright © 2011-2022 走看看