C++ Primer 5th笔记(chap 16 模板和泛型编程)模板实参推断和引用

2024-03-28 08:48

本文主要是介绍C++ Primer 5th笔记(chap 16 模板和泛型编程)模板实参推断和引用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

template < typename T> void f (T &p)
函数参数p是一个模板类型参数T的引用, 编译器会应用正常的引用绑定规则; const 是底层的, 不是顶层的

1.1 从左值引用函数参数推断类型

函数参数的类型

  • 一个普通( 左值) 引用时( 形如 T & )

绑定规则:传递一个左值( 一个变量或一个返回引用类型的表达式)。实参可以是 const 类型, 也可以不是。

如果实参是 const 的, 则 T 将被推断为 const 类型:
template <typename T> void f1 ( T& ) ; / / 实参必须是一个左值/ / 对 fl 的调用使用实参所引用的类型作为模板参数类型
fl (i)/ / i 是一个int; 模板参数类型 T 是 int
fl (ci) ; // ci 是一个 const int; 模板参数 T 是 const int
fl (5 ); / / 错误: 传递给一个&参数的实参必须是一个左值
  • const T&
    绑定规则:可以传递给它任何类型的实参 个对象( const 或非 const)、 一个临时对象或是一个字面常量值。

  • 函数参数本身是 const 时,T 的类型推断的结果不会是一个const类型。 const已经是函数参数类型的一部分; 因此, 它不会也是模板参数类型的一部分:

template <typename T> void f2 (const T & ) ; / / 可以接受一个右值
// f2 中的参教是 const &; 实参中的 const 是无关的
// 在每个调用中, f2 的函数参数都被推断为 const int &
f2 (i); / / i是一个 int; 模板参数 T 是 int
f2 (ci) ; // ci 是一个 const int , 但模板参数 T 是 int
f2 (5 ) ; // 一个 const &参数可以绑定到一个右值; T 是 int

1.2 从右值引用函数参数推断类型

当一个函数参数是一个右值引用(形如 T &&)

绑定规则:传递给它一个右值。 类型推断过程类似普通左值引用函数参数的推断过程。 推断出的 T 的类型是该右值实参的类型:

template <typename T> void f3 (T &&) ;
f3 (42) ; // 实参是一个 int 类型的右值; 模板参数 T 是 int

1.3 引用折叠和右值引用参数

假定i是一个 int 对象, 我们可能认为像 f3(i) 这样的调用是不合法的。 毕竟,i是一个左值, 而通常我们不能将一个右值引用绑定到一个左值上。 但 C++语言在正常绑定规则之外定义了两个例外规则, 允许这种绑定。

1.3.1规则1

影响右值引用参数的推断如何进行。 当我们将一个左值( 如i) 传递给函数的右值引用参数, 且此右值引用指向模板类型参数( 如 T &&) 时, 编译器推断模板类型参数为实参的左值引用类型。 因此, 当我们调用 f3(i)时, 编译器推断 T 的类型为int&,而非int。
T 被推断为 int &看起来好像意味着 f3 的函数参数应该是一个类型int &的右值引用。

1.3.2 规则2

如果我们间接创建一个引用的引用, 则这些引用形成了‘‘ 折叠”。 在所有情况下( 除了一个例外), 引用会折叠成一个普通的左值引用类型。 在新标准中, 折叠规则扩展到右值引用。 只在一种特殊情况下引用会折叠成右值引用: 右值引用的右值引用。 即, 对于一个给定类型 X:

  • X & &、 X & & &和 X & & &都折叠成类型 X &
  • 类型 X & & & &折叠成 X & &
f3(i); //实参是一个左值; 模板参数 T 是int &
f3(ci); //实参是一个左值; 模板参数 T 是一个 const int &

当一个模板参数 T 被推断为引用类型时, 折叠规则告诉我们函数参数 T & &折叠为一个左值
引用类型。 例如, f3 (i) 的实例化结果可能像下面这样:

//无效代码. 只是用于演示目的
void f3<int &> (int & & & ); // 当 T 是 int &时, 函数参数为 int &

f3 的函数参数是 T&&且 T是int&, 因此T&&是int&&&, 会折叠成int&。 因此, 即使f3 的函数参数形式是一个右值引用(即T&&), 此调用也会用一个左值引用类型(即int&) 实例化 f3:

void f3<int&> (int & ); // 当 T 是 int &时, 函数参数折叠为 int &

这两个规则导致了两个重要结果:
• 如果一个函数参数是一个指向模板类型参数的右值引用( 如T&&), 则它可以被绑定到一个左值;
• 如果实参是一个左值, 则推断出的模板实参类型将是一个左值引用, 且函数参数将被实例化为一个( 普通) 左值引用参数(T &)

另外值得注意的是, 这两个规则暗示, 我们可以将任意类型的实参传递给 T&&类型的函数参数。 对于这种类型的参数, ( 显然) 可以传递给它右值, 而如我们刚刚看到的, 也可以传递给它左值

这篇关于C++ Primer 5th笔记(chap 16 模板和泛型编程)模板实参推断和引用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/855090

相关文章

Win32下C++实现快速获取硬盘分区信息

《Win32下C++实现快速获取硬盘分区信息》这篇文章主要为大家详细介绍了Win32下C++如何实现快速获取硬盘分区信息,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 实现代码CDiskDriveUtils.h#pragma once #include <wtypesbase

C++ Primer 标准库vector示例详解

《C++Primer标准库vector示例详解》该文章主要介绍了C++标准库中的vector类型,包括其定义、初始化、成员函数以及常见操作,文章详细解释了如何使用vector来存储和操作对象集合,... 目录3.3标准库Vector定义和初始化vector对象通列表初始化vector对象创建指定数量的元素值

C++实现回文串判断的两种高效方法

《C++实现回文串判断的两种高效方法》文章介绍了两种判断回文串的方法:解法一通过创建新字符串来处理,解法二在原字符串上直接筛选判断,两种方法都使用了双指针法,文中通过代码示例讲解的非常详细,需要的朋友... 目录一、问题描述示例二、解法一:将字母数字连接到新的 string思路代码实现代码解释复杂度分析三、

C++一个数组赋值给另一个数组方式

《C++一个数组赋值给另一个数组方式》文章介绍了三种在C++中将一个数组赋值给另一个数组的方法:使用循环逐个元素赋值、使用标准库函数std::copy或std::memcpy以及使用标准库容器,每种方... 目录C++一个数组赋值给另一个数组循环遍历赋值使用标准库中的函数 std::copy 或 std::

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

c++中std::placeholders的使用方法

《c++中std::placeholders的使用方法》std::placeholders是C++标准库中的一个工具,用于在函数对象绑定时创建占位符,本文就来详细的介绍一下,具有一定的参考价值,感兴... 目录1. 基本概念2. 使用场景3. 示例示例 1:部分参数绑定示例 2:参数重排序4. 注意事项5.

使用C++将处理后的信号保存为PNG和TIFF格式

《使用C++将处理后的信号保存为PNG和TIFF格式》在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_ima... 目录1. PNG格式保存使用stb_imagephp_write库1.1 安装和包含库1.2 代码解