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

相关文章

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Python异步编程之await与asyncio基本用法详解

《Python异步编程之await与asyncio基本用法详解》在Python中,await和asyncio是异步编程的核心工具,用于高效处理I/O密集型任务(如网络请求、文件读写、数据库操作等),接... 目录一、核心概念二、使用场景三、基本用法1. 定义协程2. 运行协程3. 并发执行多个任务四、关键

AOP编程的基本概念与idea编辑器的配合体验过程

《AOP编程的基本概念与idea编辑器的配合体验过程》文章简要介绍了AOP基础概念,包括Before/Around通知、PointCut切入点、Advice通知体、JoinPoint连接点等,说明它们... 目录BeforeAroundAdvise — 通知PointCut — 切入点Acpect — 切面

C++ STL-string类底层实现过程

《C++STL-string类底层实现过程》本文实现了一个简易的string类,涵盖动态数组存储、深拷贝机制、迭代器支持、容量调整、字符串修改、运算符重载等功能,模拟标准string核心特性,重点强... 目录实现框架一、默认成员函数1.默认构造函数2.构造函数3.拷贝构造函数(重点)4.赋值运算符重载函数

C++ vector越界问题的完整解决方案

《C++vector越界问题的完整解决方案》在C++开发中,std::vector作为最常用的动态数组容器,其便捷性与性能优势使其成为处理可变长度数据的首选,然而,数组越界访问始终是威胁程序稳定性的... 目录引言一、vector越界的底层原理与危害1.1 越界访问的本质原因1.2 越界访问的实际危害二、基

Python学习笔记之getattr和hasattr用法示例详解

《Python学习笔记之getattr和hasattr用法示例详解》在Python中,hasattr()、getattr()和setattr()是一组内置函数,用于对对象的属性进行操作和查询,这篇文章... 目录1.getattr用法详解1.1 基本作用1.2 示例1.3 原理2.hasattr用法详解2.

C#异步编程ConfigureAwait的使用小结

《C#异步编程ConfigureAwait的使用小结》本文介绍了异步编程在GUI和服务器端应用的优势,详细的介绍了async和await的关键作用,通过实例解析了在UI线程正确使用await.Conf... 异步编程是并发的一种形式,它有两大好处:对于面向终端用户的GUI程序,提高了响应能力对于服务器端应

c++日志库log4cplus快速入门小结

《c++日志库log4cplus快速入门小结》文章浏览阅读1.1w次,点赞9次,收藏44次。本文介绍Log4cplus,一种适用于C++的线程安全日志记录API,提供灵活的日志管理和配置控制。文章涵盖... 目录简介日志等级配置文件使用关于初始化使用示例总结参考资料简介log4j 用于Java,log4c

C++归并排序代码实现示例代码

《C++归并排序代码实现示例代码》归并排序将待排序数组分成两个子数组,分别对这两个子数组进行排序,然后将排序好的子数组合并,得到排序后的数组,:本文主要介绍C++归并排序代码实现的相关资料,需要的... 目录1 算法核心思想2 代码实现3 算法时间复杂度1 算法核心思想归并排序是一种高效的排序方式,需要用

C# async await 异步编程实现机制详解

《C#asyncawait异步编程实现机制详解》async/await是C#5.0引入的语法糖,它基于**状态机(StateMachine)**模式实现,将异步方法转换为编译器生成的状态机类,本... 目录一、async/await 异步编程实现机制1.1 核心概念1.2 编译器转换过程1.3 关键组件解析