IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【c++ 11】auto和decltype的区别和联系 -> 正文阅读

[C++知识库]【c++ 11】auto和decltype的区别和联系

1.auto类型推导的语法和规则


????????C++11 赋予 auto 关键字新的含义,使用它来做自动类型推导。也就是说,使用了 auto 关键字以后,编译器会在编译期间自动推导出变量的类型,这样我们就不用手动指明变量的数据类型了。

????????auto 关键字的使用:还有一个值得注意的地方是:使用 auto 类型推导的变量必须马上初始化,这个很容易理解,因为 auto 在 C++11 中只是“占位符”,并非如 int 一样的真正的类型声明。

auto test = 2;

auto n = 10;         // int
auto f = 12.8;       // double
auto p = &n;         // int *
auto url = "http://c.biancheng.net/cplus/";   // 常量指针 const char*


int  x = 0;
const  auto n = x;   //n 为 const int ,auto 被推导为 int
auto f = n;          //f 为 const int,auto 被推导为 int(const 属性被抛弃)
const auto &r1 = x;  //r1 为 const int& 类型,auto 被推导为 int
auto &r2 = r1;       //r1 为 const int& 类型,auto 被推导为 const int 类型

// auto 仅仅占用一个字符位,在编译期间会被真正的类型代替

最后我们来简单总结一下 auto 与 const 结合的用法:

????????当类型不为引用时,auto 的推导结果将不保留表达式的 const 属性;

????????当类型为引用时,auto 的推导结果将保留表达式的 const 属性。

1.1 使用auto的限制

??????? 1)auto不能在函数的参数中使用

??????? 2)auto不能作用于类的非静态成员变量(也就是没有static关键词修饰的成员变量中)

??????? 3)auto关键字不能定义数组

??????? 4)auto不能作用于模板参数

1.2 auto的使用场景

??????? 1)auto 的一个典型应用场景是用来定义 stl 的迭代器。

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<vector<int> > test;
    vector< vector<int> >::iterator i = v.begin();   // auto i = v.begin();
    return 0;
}

??????? 2)auto可以用于泛型编程

    #include <iostream>
    using namespace std;
    class A{
    public:
        static int get(void){
            return 100;
        }
    };
    class B{
    public:
        static const char* get(void){
            return "http://c.biancheng.net/cplus/";
        }
    };
    template <typename T>
    void func(void){
        auto val = T::get();
        cout << val << endl;
    }
    int main(void){
        func<A>();
        func<B>();
        return 0;
    }

2.decltype (declare type)

使用方法:

auto varname = value;
decltype(exp) varname = value;

decltype(exp) varname; // correct

//auto 根据=右边的初始值 value 推导出变量的类型,而 decltype 根据 exp 表达式推导出变量的类型,跟=右边的 value 没有关系。
//auto 要求变量必须初始化,而 decltype 不要求

2.1 decltype推导规则

??????? 1.如果 exp 是一个不被括号( )包围的表达式,或者是一个类成员访问表达式,或者是一个单独的变量,那么 decltype(exp) 的类型就和 exp 一致,这是最普遍最常见的情况。

??????? 2.如果 exp 是函数调用,那么 decltype(exp) 的类型就和函数返回值的类型一致。

??????? 3.如果 exp 是一个左值,或者被括号( )包围,那么 decltype(exp) 的类型就是 exp 的引用;假设 exp 的类型为 T,那么 decltype(exp) 的类型就是 T&。

//函数声明
int& func_int_r(int, char);  //返回值为 int&
int&& func_int_rr(void);  //返回值为 int&&
int func_int(double);  //返回值为 int

const int& fun_cint_r(int, int, int);  //返回值为 const int&
const int&& func_cint_rr(void);  //返回值为 const int&&

//decltype类型推导
int n = 100;
decltype(func_int_r(100, 'A')) a = n;  //a 的类型为 int&
decltype(func_int_rr()) b = 0;  //b 的类型为 int&&
decltype(func_int(10.5)) c = 0;   //c 的类型为 int

decltype(fun_cint_r(1,2,3))  x = n;    //x 的类型为 const int &
decltype(func_cint_rr()) y = 0;  // y 的类型为 const int&&

// exp 中调用函数时需要带上括号和参数,但这仅仅是形式,并不会真的去执行函数代码。
    using namespace std;
    class Base{
    public:
        int x;
    };
    int main(){
        const Base obj;
        //带有括号的表达式
        decltype(obj.x) a = 0;  //obj.x 为类的成员访问表达式,符合推导规则一,a 的类型为 int
        decltype((obj.x)) b = a;  //obj.x 带有括号,符合推导规则三,b 的类型为 int&。
        //加法表达式
        int n = 0, m = 0;
        decltype(n + m) c = 0;  //n+m 得到一个右值,符合推导规则一,所以推导结果为 int
        decltype(n = n + m) d = c;  //n=n+m 得到一个左值,符号推导规则三,所以推导结果为 int&
        return 0;
    }

2.2 decltype使用场景

??????? 类的成员变量:

    #include <vector>
    using namespace std;
    template <typename T>
    class Base {
    public:
        void func(T& container) {
            m_it = container.begin();
        }
    private:
        typename T::iterator m_it;  //注意这里
    };
    int main()
    {
        const vector<int> v;
        Base<const vector<int>> obj;
        obj.func(v);
        return 0;
    }

????????在使用 Base 类的时候,如果传入一个 const 类型的容器,编译器马上就会弹出一大堆错误信息。原因就在于,T::iterator并不能包括所有的迭代器类型,当 T 是一个 const 容器时,应当使用 const_iterator。

?

    template <typename T>
    class Base {
    public:
        void func(T& container) {
            m_it = container.begin();
        }
    private:
        decltype(T().begin()) m_it;  //注意这里
    };

3. auto和decltype的区别

????????第一:auto类型说明符用编译器计算变量的初始值来推断其类型,而decltype虽然也让编译器分析表达式并得到它的类型,但是不实际计算表达式的值。

????????第二:编译器推断出来的auto类型有时候和初始值的类型并不完全一样,编译器会适当地改变结果类型使其更符合初始化规则。例如,auto一般会忽略掉顶层const,而把底层const保留下来。与之相反,decltype会保留变量的顶层const。

????????第三:与auto不同,decltype 的结果类型与表达式形式密切相关,如果变量名加上了一对括号,则得到的类型与不加括号时会有不同。如果 decltype使用的是一个不加括号的变量,则得到的结果就是该变量的类型;如果给变量加上了一层或多层括号,则编译器将推断得到引用类型。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-31 11:35:33  更:2022-10-31 11:38:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 3:42:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码