C++精要分析decltype的作用及用法

 更新时间:2022年05月09日 10:41:46   作者:程序猿阿诺  
decltype是C++11新增的一个关键字,和auto的功能一样,用来在编译时期进行自动类型推导。引入decltype是因为auto并不适用于所有的自动类型推导场景,在某些特殊情况下auto用起来很不方便,甚至压根无法使用

获取表达式的类型

在编写程序的过程中,我们可能会有一种需求,就是希望可以根据一个变量的类型,来定义具有相同类型的变量。例如定义int x = 0;,那么我们是否可以不使用int关键字,仅使用x就定义一个新的整型变量y呢?

答案是可以的,C++11新增的decltype关键字就是干这个用的。上述需求用代码实现如下:

int x = 0;
decltype(x) y = 2; // y的类型为int

decltype是在编译期用来推导表达式类型的。其语法格式为:decltype(expression)。大家可以看到,decltype是可以对一个表达式取类型的,并不仅是单个的变量。所以,把形式再扩展一下:

int x = 0;
decltype(x) y = 2;
decltype(x + y) z = 3; // z的类型为int

到这一步,相信大家已经可以基本掌握其特性,在工作中能运用了。当然,仅知道这些还是不够的,作为C++程序员怎么能停下探索的脚步呢。

推导规则

decltype的推导规则,是面试中最容易挖坑的地方。你要是不信,那就先回答下面这些问题吧:

const int func_one();
decltype(func_one()) a1 = 0; // a1是什么类型?
struct TestData { int x;};
cosnt TestData b_node = TestData();
decltype(b_node.x) b1 = 0; // b1是什么类型?
decltype((b_node.x)) b2 = b1; // b2是什么类型?
int n = 0, m = 0;
decltype(n + m) c1 = 0; // c1是什么类型?
decltype(n += m) c2 = c1; // c2是什么类型?

注释中有五个问题,如果你全都答对而且不是蒙的,那请开班授课吧,我会第一个报名。先公布一下答案,看看自己答对了多少吧。

a1: int
b1: int
b2: const int &
c1: int 
c2: int &

如果这个答案让你觉得有些晕头转向,不要紧,先来看下规则描述吧:

  1. 如果expression表达式是标识符、类访问表达式,decltype(exp)和exp的类型一致;
  2. 如果expression是函数调用,则decltype(exp)和返回值的类型一致;
  3. 其他情况,如果expression是一个左值,则decltype(exp)是exp类型的左值引用,否则和exp类型一致。

现在,将规则理解之后,再看一遍代码和答案,是否找到规律了呢?相信在面试中遇到这样的问题,你已经可以应对自如了。

返回类型后置

在说明decltype的一个高级用法之前,我们先了解C++11的一个新特性,就是函数返回类型后置。与之相对的,就是返回类型前置,这是我们最熟悉的函数声明格式。例如:int foo();

而返回类型后置的示例如下:

auto foo() -> int {
    return 0;
}

在上面的代码中,auto关键字是一个占位符,int是其实际返回类型。初看起来,后置声明与前置声明在功能上是一样的,那它难道是一个多余的设计吗?它当然自有用武之地。

在需要返回比较复杂的类型时,使用后置式声明可以简化代码并使其可读性更好。例如要返回的类型是函数指针,前置式声明就必须先用typedef进行预定义,否则语法不允许。而后置式声明则可以直接实现,无需预定义,如下代码所示。

int exam(bool b) {
    int ret = -1;
    if (b) {
        ret = 0;
    }
    else if (!b) {
        ret = 1;
    }
    return ret;
}
auto foo() -> int(*)(bool) {
    return exam;
}
int main() {
    auto fn = foo();
    cout << fn(true) << endl;
    cout << fn(false) << endl;
}

高级用法

现在正式介绍decltype与函数返回类型后置相结合,在模板编程中的用法,就是用于推导函数模板的返回类型。之所以将此归为高级用法,也是因为模板在C++中虽然功能强大,但属实复杂不易理解。一般是编写基础功能库或是算法库时,使用到模板的特性。

先看一段示例代码:

template<class T1, class T2>
auto sum(T1 t1, T2 t2) -> decltype(t1 + t2) {
    return t1 + t2;
}
int main() {
    auto ret = sum(4.6, 123);
    cout << ret << endl;
}

其精髓之处,就在于可以灵活支持T1与T2不同类型的组合,而不必为每种返回类型都去写一个实现。例如int+int, double+int, string+string等各种组合情况。

但如果是把decltype(t1 + t2)以前置写法替换auto,则会产生编译错误。道理很简单,编译器对t1+t2的参数类型还一无所知,只有在解析到返回值时,才能最终确定函数的返回类型,这就是decltype加上函数返回类型后置在模板编程中的妙用。

到此这篇关于C++精要分析decltype的作用及用法的文章就介绍到这了,更多相关C++ decltype内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++中string使用+号与int拼接方式

    C++中string使用+号与int拼接方式

    这篇文章主要介绍了C++中string使用+号与int拼接方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • C++ 十进制转换为二进制的实例代码

    C++ 十进制转换为二进制的实例代码

    这篇文章介绍了C++ 十进制转换为二进制的实例代码,有需要的朋友可以参考一下
    2013-10-10
  • C语言实现静态版通讯录的示例代码

    C语言实现静态版通讯录的示例代码

    这篇文章主要为大家详细介绍了如何利用C语言实现一个简单的静态版通讯录,文中的示例代码讲解详细,对我们学习C语言有一定帮助,需要的可以参考一下
    2022-08-08
  • C++ 将一个文件读入数组再读出数组的方法

    C++ 将一个文件读入数组再读出数组的方法

    今天小编就为大家分享一篇C++ 将一个文件读入数组再读出数组的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07
  • C++中新手容易犯的十种编程错误汇总

    C++中新手容易犯的十种编程错误汇总

    一段C语言代码,在编译、链接和运行的各个阶段都可能会出现问题,下面这篇文章主要给大家介绍了关于C++中新手容易犯的十种编程错误的相关资料,需要的朋友可以参考下
    2021-10-10
  • C语言规避野指针的方法流程

    C语言规避野指针的方法流程

    野指针就是指针指向的不是一个有效(合法)的地址,在程序中,如果访问野指针,可能会造成程序的崩溃,这篇文章主要介绍了C语言如何规避野指针,需要的朋友可以参考下
    2024-03-03
  • OpenGL绘制贝塞尔曲线

    OpenGL绘制贝塞尔曲线

    这篇文章主要为大家详细介绍了OpenGL绘制贝塞尔曲线,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • C++深入分析数据在内存中的存储形态

    C++深入分析数据在内存中的存储形态

    使用编程语言进行编程时,需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着,当您创建一个变量时,就会在内存中保留一些空间。您可能需要存储各种数据类型的信息,操作系统会根据变量的数据类型,来分配内存和决定在保留内存中存储什么
    2023-01-01
  • C语言实现销售管理系统设计

    C语言实现销售管理系统设计

    这篇文章主要为大家详细介绍了C语言实现销售管理系统设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Android App仿微信界面切换时Tab图标变色效果的制作方法

    Android App仿微信界面切换时Tab图标变色效果的制作方法

    这篇文章主要介绍了Android App仿微信界面切换时Tab图标变色效果的制作方法,重点讲解了图标的绘制技巧,需要的朋友可以参考下
    2016-04-04

最新评论