C++学习:Effective Modern C++条款

读书笔记:《Effective Modern C++(C++14)》 使用RAII(“Resource Acquisition Is Initialization,资源获得即初始化)包装thread,在析构时进行join。和闭包类存在于编译期,闭包存在于运行时。 阅读详情

条款1:理解模板类型推导

  • 推导模版类型时,引用的值视为非引用,即忽略引用。
  • 推导通用引用类型参数时,左值特殊处理。
  • 推导传值参数时,忽略const和volatile。
    +推导模版类型时,参数是数组或函数名则退化为指针,除非用来初始化引用。

条款2:理解auto类型推导

  • 推导auto类型一般和推导模版类型是一致的,但auto类型推导对于大括号初始化{}会推导为std::initializer_list,模版类型推导则不会。
  • 做为函数返回类型或lambda参数中的auto类型推导意味着模版类型推导,而不做为auto类型推导。

条款3:理解decltype.

  • decltype几乎总是推导出变量或表达式的类型,不做任何修改。
  • 类型为T的左值表达式而不是名称,decltype总是推导成引用T&。
  • C++14支持decltype(auto),和auto一样,通过初始值推导,但使用decltype规则。

条款4:知道如何查看推导出来的类型.

  • 推导出来的类型通常可以使用IDE编辑器,编译错误信息或Boost TypeIndex库查看到。
  • 有些工具查看到的结果可能没有任何帮助或者就是错误的,所以理解类型推导规则还是有用的。

条款5:优先使用auto,而不是显式的类型声明

  • auto变量必须初始化,基本上不会有类型不匹配导致的可移值问题或效率问题的影响,也可以简化重构过程,一般也比显式指定类型需要更少的键盘输入。
  • auto类型的变量请查看条款2和条款6中描述的陷阱。

条款6:当auto推导出的类型不是想要的类型时,使用显示类型初始化的惯用语法。

  • “不可见的”代理类型会导致auto对初始化表达式推导出“错误的”类型。
  • 显示类型初始化的惯用语法迫使auto推导出想要的类型。

条款7:创建对象时区分()和{}。

  • 花括号初始化方法是最为广泛使用的初始化语法,可以防止类型转换变窄,也不受C++烦人的解析问题影响。
  • 构造函数的重载解析中,花括号初始化方法只要可能就会匹配std::initializer_list参数,即使有其它的构造函数提供了看上去更好的匹配参数。
  • std::vector<数字类型>在使用圆括号和花括号初始化时意义完全不同。
  • 在模板中的对象创建时选择圆括号还是花括号是一个挑战。

条款8:优先使用nullptr,而不是0和NULL。

  • 优先使用nullptr,而不是0和NULL。
  • 避免整形或指针类型的重载。

条款9:优先使用alias声明,而不是typedef。

  • typedefs不支持模板化,alias声明支持。
  • alias模板避免了“::type”后缀,以及在模板中的用于typedefs的“typename”前缀。
  • 所有C++11中类型traits转换,C++14都提供了alias模板。

条款10:优先使用范围枚举,而不是非范围枚举。

  • C++98类型的枚举就是非范围枚举。
  • 范围枚举的枚举器只在枚举内部可见,只能通过cast转换为其它类型。
  • 范围枚举和非范围枚举都支持指定底层类型。范围枚举的默认底层类型是int, 而非范围没有默认底层类型。
  • 范围枚举总是可以前向声明,而非范围枚举只有指定底层类型时才可以前向声明。

条款11:优先使用deleted函数,而不是私有未定义函数。

  • 优先使用deleted函数,而不是私有未定义函数。
  • 任何函数都可以deleted, 包括非成员函数和模板实例函数。

条款12:把重写函数声明为override

  • 把重写函数声明为override。
  • 成员函数引用限定符可以区别对待左值和右值对象。

条款13:优先使用const_iterator, 而不是其它的iterator。

  • 优先使用const_iterator, 而不是其它的iterator。
  • 大多数泛型代码中,优先使用非成员函数版本的begin, end, rbegin等等,而不是相应的成员函数。

条款14:如果函数不抛出异常则声明为noexcept

  • noexcept是函数接口的一部分,意味着调用者必须依赖它。
  • noexcept函数更容易优化。
  • noexcept在移动操作,交换,内存释放函数,析构函数中特别有价值。
  • 大多数函数是异常中立的,而不是noexcept。

条款15:只要有可能就使用constexpr。

  • constexpr对象是常量并且是在编译期初始化的。
  • constexpr函数在给定的参数是编译期已知的情况下可以生成编译期结果。
  • constexpr对象和函数比起非constexpr对象和函数,可以使用在更宽泛的上下文范围。
  • constexpr是对象接口或函数接口的一部分。

条款16:使const成员成为线程安全的。

  • 除非确定不会在并发环境中使用,否则const成员一定要是线程安全的。
  • std::atomic变量比mutex性能更好,但只能用于操作单一变量或单一内存位置。

条款17:理解特殊成员函数的生成。

  • 特殊成员函数就是编译器自动生成的:默认构造函数,析构函数,拷贝操作,移动操作。
  • 移动操作函数只有在没有显式声明移动操作,拷贝操作,析构函数时才会生成。
  • 拷贝构造函数只有在没有显式声明拷贝构造函数时才会生成,而且如果声明了移动操作就会被删除。拷贝赋值操作只有在没有显式声明拷贝赋值操作符才会生成,而且声明了移动操作就会删除。如果显式声明了析构函数,则拷贝操作就会过时。
  • 成员函数模板永远不会阻止特殊成员函数的生成。

条款18:使用std::unique_ptr管理独占资源。

  • std::unique_ptr小巧,快速,只能移动,用于管理独占资源。
  • 默认情况下资源析构使用delete, 但可以指定自定义的删除器。有状态的删除器或函数指针会增加std::unique_ptr对象的大小。
  • std::unique_ptr很容易转换为std::shared_ptr。

条款19: 使用std::shared_ptr管理共享资源。

  • std::shared_ptrs对于随意的资源的共享生命周期管理提供方便的垃圾回收处理方法。
  • 相对于std::unique_ptr来说,std::shared_ptr对象通常大一倍,主要是控制块,原子引用计数操作导致。
  • 默认资源的析构是通过delete, 但也支持自定义删除器。删除器的类型对std::shared_ptr的类型不起作用。
  • 避免从原始指针类型的变量生成std::shared_ptrs。

条款20:使用std::weak_ptr代替可能会发生悬空指针的std::shared_ptr。

  • 使用std::weak_ptr代替可能会发生悬空指针的std::shared_ptr。
  • 潜在的使用std::weak_ptr的情景有缓存,观察者列表,避免std::shared_ptr循环引用。

条款21:优先使用std::make_unique和std::make_shared,而不是直接使用new。

  • 相对于直接使用new来说,make函数消除了源代码重复,提升了异常安全,而且std::make_shared和std::allocate_shared都会生成更小更快的代码。
  • 不适合使用make函数的情况有指定自定义的删除器,需要传递括号初始化器。
  • 对std::shared_ptrs来说,make函数不推荐使用的其它情况还有(1)有自定义内存管理的类(2)有内存问题的系统,非常大的对象,以及std::weak_ptrs比std::shared_ptrs的生命还要长的情况。

条款22:如果使用Pimpl惯用法,则要在实现文件中定义特殊成员函数。

  • Pimpl惯用法通过减少类的实现和类的客户的编译依赖关系缩减了编译时间。
  • 如果std::unique_ptr用于pImpl指针,则在类的头文件中声明特殊成员函数,在实现文件中实现。即使默认的函数实现可以接受的话也要这么做。
  • 以上建议适用于std::unique_ptr,但不适用于std::shared_ptr。

条款23: 理解std::move和std::forward。

  • std::move无条件转换为右值,就其本身而言,它不移动任何东西。
  • std::forward只有在绑定的参数是右值时才会将参数转换为右值。
  • std::move和std::forward在运行时不做任何事情。

条款24:区分通用引用和右值信引用。

  • 如果函数模板参数有类型T&&并且需要推导T,或者对象声明为auto&&, 则参数或对象是通用引用。
  • 如果类型声明的格式不是精确的type&&, 或不需要类型推导,type&&就是右值引用。
  • 通用引用如果使用右值初始化的话,则和右值引用是一致的。如果是用左值初始化的话,则与左值引用是一致的。

条款25:对右值引用使用std::move, 对通用引用使用std::forward。

  • 最后一次使用时,对右值引用使用std::move, 对通用引用使用std::forward。
  • 返回值是传值时,同上面一样。
  • 如果本地对象有可能做返回值优化的话,永远也不要对本地对象使用std::move或std::forward。

条款26:避免对通用引用进行重载。

  • 重载通用引用几乎总是超预期地频繁调用了通用引用的重载。
  • 完美转发构造函数特别有问题,因为比non-const左值的拷贝构造函数有更好的匹配,这样就会派生类调用基类的拷贝构造函数和移动构造函数。

条款27:熟悉重载通用引用函数的其它替代方法

  • 通用引用和重载的组合的替代方法有使用不同的函数名,通过常量的左值引用传递参数,通过值传递参数,以及使用标记调度。
  • 通过std::enable_if约束模板可以允许通用引用和重载一起使用,但会控制编译器使用通用引用重载的条件。
  • 通用引用参数经常会有提升效率的优点,但是通常也会有使用上的缺点。

条款28:理解引用折叠。

  • 引用折叠发生在四种情况:模板实例化,自动类型生成,typedef和alias声明的创建和使用,decltype。
  • 当编译器在引用折叠环境中生成引用的引用时,结果就会成为单引用。如果原始的引用有一个是左值引用,则结果就是左值引用,否则就是右值引用。
  • 通用引用是右值引用的情况有,类型推导可以区分左值和右值时,以及发生引用折叠时。

条款29: 要假定移动操作是不存在在,不是廉价的,也不是可用的。

  • 要假定移动操作是不存在在,不是廉价的,也不是可用的。
  • 已知类型或支持移动语义类型的代码中,不需要有假定。

条款30:熟悉完美转发失败案例。

  • 如果模板类型推导失败或推导出错误的类型时,完美转发就会失败。
  • 导致完美转发失败的参数类型有括号初始化器,使用0或NULL的指针,整形常量静态数据成员的声明,模板和重载函数名称,位成员。

条款31:避免默认的捕捉模式。

  • 默认的传引用操作捕捉会导致悬空引用。
  • 默认的传值操作捕捉容易受悬空指针影响(特别是这里),并且会误导成lambdas是自包含的。

条款32:使用init捕捉来移动对象到闭包。

  • 使用c++14的init捕捉来移动对象到闭包。
  • C++11中,通过手写的类或std::bind来模仿init捕捉。

条款33:使用decltype调用std::forward移动auto&&参数。

  • 使用decltype调用std::forward移动auto&&参数。

条款34:优先使用lambdas,而不是std::bind

  • Lambdas更容易阅读,更快捷,并且比std::bind更高效。
  • 只有在C++11中,std::bind在实现移动捕捉或绑定对象到模板化的函数调用操作符上可能会有用。

条款35:优先采用基于task的编程方法,而不是基于thread(相关的类)。

  • std::thread API从异步运行函数中得到非直接的结果,如果函数抛出异常,则程序终止。
  • 基于Thread的编程方法调用需要手工管理线程耗尽、过度订阅、负载均衡,以及适应新平台等问题。
  • 基于Task的编程方法通过std::async使用默认加载策略来处理大多数的问题。

条款36:如果需要异步处理,请指定std::launch::async。

  • std::async的默认加载策略既允许异步执行,也允许同步的执行。
  • 灵活性也会导致访问thread_local时产生不确定性,线程也许永远不会执行,也会影响基于超时等待调用的程序逻辑。
  • 如果需要异步处理,请指定std::launch::async。

条款37:使std::threads在任何路径下都是不能join的。

  • 使std::threads在任何路径下都是不能join的。
  • 在析构函数上join会导致难以调试的性能问题。
  • 在析构函数上detach会导致难以调试的未定义行为。
  • 将std::thread对象做为数据成员列表项中的最后一个。

条款38:要小心不同的线程句柄析构行为。

  • Future的析构函数通常只会销毁future的数据成员。
  • 涉及到非延期task的共享状态的final future是通过std::async,在task完成后加载的。

条款39: 考虑对于一次性事件通信中使用void future。

  • 对于简单的事件通信,基于condvar的设计需要一个多余的互斥量,对检测和响应任务的相应进度施加限制,并且需要响应任务验证事件是否已发生。

  • 设计使用一个标记来避免这些问题,但这是基于轮询的,而不是基于阻塞的。

  • condvar和标记可以一起使用,但结果通信机制会有点不自然。

  • 使用std::promises和futures来回避这些问题,但是这种方法使用堆内存来处理共享状态,并且只能用于一次性通信。

条款40:使用std::atomic处理并发,使用volatile处理特殊内存。

  • std::atomic用来在不使用mutex的多线程情形下访问数据。它是编写并发软件的一个工具。
  • volatile用来在读写操作不是优化的方式下处理内存。它是编写处理特殊内存的一个工具。

条款41: 考虑使用传值来处理移动操作很廉价而且总是被拷贝的参数(如果移动没有提高性能的话,编译器可能就直接优化成拷贝了)

  • 对于能够拷贝,移动操作很廉价而且总是被拷贝的参数,传值跟传引用基本上同样高效,而且更容易实现,产生更少的代码。
  • 通过构造函数拷贝参数可能比通过赋值操作符拷贝参数更加高昂。
  • 传值操作会有切片问题,所以一般对于基类参数类型不适合。

条款42:考虑使用emplace的函数,而不是insert函数

  • 原则上,emplace的函数有时应该比插入函数效率更高,而且效率永远不会降低。
  • 在实践中,以下情形(emplace的函数)可能更快:(1)要添加的值是构造到容器中时,而不是赋值到容器中(2)传递的参数类型与容器中的类型不同(3)容器不会排斥要添加的值,因为它是重复的值。
  • Emplace的函数有可能执行类型转换,而insert的函数会排斥。
effective modern c++ 学习笔记1 C++11引入了lambda表达式,它是一种创建匿名闭包的语法糖,可以方便地定义和使用闭包,其中capture list指定了要捕获的外部变量,可以是值捕获或引用捕获。C++11提供了std::function模板类,它是一种通用的函数对象包装器**,可以存储任何可调用的对象,包括普通函数、成员函数、函数对象、lambda表达式等³。std::function可以用来作为闭包的参数或返回值,提高了闭包的灵活性和通用性。 阅读详情

相关推荐

EffectiveC++中文版

EffectiveC++中文版 pdf高清非扫描版本 从 C 转向 C++ 对每个人来说,习惯 C++需要一些时间,对于已经熟悉 C 的程序员来说, 这个过程尤其令人苦恼。因为 C 是 C++的子集,所有的 C 的技术都可以继续使用,但很多用。。。

Effective Modern C++

形参表明通过通信信道被传递的信息的类型。这种模板的实例化(比如,std::atomic,std::atomic,std::atomic<Widget*>等)提供了一种在其他线程看来操作是原子性的的保证(译注:即某些操作是像原子一样的不可分割。std::function的实例可以存储、复制和调用任何可调用对象,存储的可调用对象称为std::function的目标,若std::function不含目标,则称它为空,调用空的std::function的目标会抛出std::bad_function_call异常。

ltd0924的博客 1378

Effective.Modern.C++中文版和英文版.zip

Effective.Modern.C++中文版和英文版

Effective Modern C++ 纯人工翻译,持续更新,不为博你眼球,旨在自我提升

纯手动翻译Effective Modern C++,志在学习,不为博你眼球!

2114

【强化学习】强化学习中,训练过程的稳定性是什么?该如何进行衡量?请详细进行解释

在强化学习中,训练过程的稳定性指的是算法在训练过程中表现出一致的行为,并且能够稳定地收敛到一个好的策略。收敛性:算法是否能够在有限的时间内收敛到一个近似最优的策略。鲁棒性:算法在不同的初始条件或环境扰动下的表现是否稳定。方差:算法在多次运行中表现出的变异程度。稳定的训练过程意味着算法的训练曲线平滑奖励信号变化小,且策略或价值函数的变化是渐进的。

wq6qeg88的博客 1628

告别环境依赖!用PyInstaller把PaddleOCR项目打包成独立EXE(附完整spec文件配置)

本文详细介绍了如何使用PyInstaller将PaddleOCR项目打包成独立EXE文件,彻底解决Python环境依赖问题。通过完整的spec文件配置和实战技巧,开发者可以轻松创建开箱即用的OCR工具,特别适合需要交付给非技术用户的场景。文章涵盖环境配置、模型打包、性能优化等关键环节,并提供了解决常见问题的方案。

weixin_33712987的博客 573

《Effective Modern C++》学习笔记之条款四十二:考虑置入而非插入

如果你有个容器,持有一些,比如说,std::string型别的对象,那么似乎合乎逻辑的做法是用某个插入函数insertion function来向其中添加新元素,比如insert,push_front和push_back,又或者对于std::forward_list而言的insert_after,而传递给函数的元素型别将是std::string。毕竟,那正是容器持有物的型别。 1. 分析为什么push_back效率不高 说合乎逻辑倒也确实合乎逻辑,但却不一定合乎事实。考虑这段代码: std::vect

王木木 7019

深入解析ADC采样电容:从充电误差到LSB精度的关键设计

本文深入解析了ADC采样电容在模数转换中的核心作用,重点探讨了充电时间常数与采样误差的博弈关系。通过推导最小采样时间公式,揭示了精度、速度、源阻抗与内部电容之间的制约关系,并提供了从理论计算到外部驱动电路设计的实战指南,是确保ADC达到LSB精度的关键。

android的专栏 1103

《Effective Modern C++》学习笔记之条款一:理解模板型别推导

模板的型别推导是现代C++最广泛应用的特性之一,下面的一小段伪代码可以简单明了的说明函数模板使用场景。函数模板定义如下:

王木木 602

T12 电烙铁简单程序逻辑

通过分析就可以知道,发热丝本身即是发热体,也是热偶的工作端。怎么可能是热电动势呢,确实,但不要忘了T12-OUTPUT端的电压是PWM波,理论上是有单片机PWM电压为0 v时的,而T12-OUTPUT端的电压此时也应为0。在T12烙铁头中,PID控制算法通过监测温度传感器的输出,计算当前温度与设定温度之间的差异,并根据这一差异调节加热功率,以实现烙铁头温度的精确控制。这段代码实现了一个简单的增量式PID控制器,通过计算当前温度与期望温度之间的差异以及历史偏差值,调节输出控制量,实现对温度的精确控制。

hgkhjkljnl的博客 1万+

Docker版OnlyOffice中文字体配置全攻略:从字号调整到字体添加

本文详细介绍了在Docker版OnlyOffice中配置中文字体和调整字号的完整方案。通过容器内操作和配置文件修改,实现中文标准字号映射及思源、阿里巴巴等优质字体的集成,提升文档排版的规范性和专业性。特别针对企业级部署提供了性能优化建议和常见问题解决方案。

weixin_28309571的博客 136

《Effective Modern C++》学习笔记之条款三:理解decltype

decltype是C++11新增的一个关键字,它的主要应用场景是哪些返回值依赖于形参型别的场景。一般来说decltype告诉你的结果与你预测的几乎相同,所以这里就不再累述,只需要记住以下几点即可: decltype(expression) var; 具体判断逻辑如下:(1)如果expression没有使用括号括起来,则类型与expression完全相同,例如 const int i =0; decltype(i) var;则var为const int.(2)如果expression是一个函数调用,则v..

王木木 497

ESP32开发进阶:1.接入文心一言

ESP32开发进阶:接入文心一言大模型,串口对话

qq_53529450的博客 1431

《Effective Modern C++》学习笔记之条款二:理解auto型别推导

首先auto型别推导与模板型别推导完全相同,唯一的区别是在对大括号括起来的表达式进行推导时,auto会将其推导为一个std::initializer_list的类型。代码示例如下: auto x1 = 27; //x1型别为int auto x2(27); //x2型别为int auto x3 = {27}; //x3型别为std::initializer_list<int> auto x4{27}; //x4型别为std::initializer_list&lt..

王木木 432

pcie硬件时序分析实战(PHY层眼图测量)​

PCIe高速接口的信号完整性(SI)直接影响系统带宽和稳定性。其中,​。

xiaoheshang_123的博客 858

在 SAP HANA 里为视图创建 Analytic Privilege,真正把同一份数据按角色切开

摘要:本文介绍了SAP HANA中基于业务角色的动态数据权限控制方法。通过Analytic Privilege技术,可以在同一视图上为不同角色设置不同的数据访问范围,实现行级安全控制。核心机制包括:1) 创建带有STRUCTURED PRIVILEGE CHECK的视图;2) 建立授权对象和用户映射表;3) 开发条件提供过程动态生成过滤条件;4) 创建结构化权限对象绑定条件提供器。这种设计使权限规则与业务数据解耦,便于维护变更,适合销售区域、财务数据等多角色访问控制场景。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 2390

《Effective Modern C++》学习笔记之条款三十一:避免默认捕获模式

C++11中有两种默认捕获方式:按值或者按引用。按值的默认捕获方式可能会忽悠你,按引用的默认捕获方式可能导致空悬引用。 按引用捕获会导致闭包包含涉及到局部变量的引用,或者涉及到定义lambda式子的作用域内形参的引用,考虑如下代码: using FilterContainer = std::vector<std::function<bool(int)>>; FilterContainer filters; void addDivisorFilter() { auto cal

王木木 1081

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

《Effective Modern C++》学习笔记之条款三十二:使用初始化捕获将对象移入闭包

如果你有一个对象,其复制操作开销昂贵,而移动操作成本低廉,而你又需要把该对象放入闭包,那么你肯定更愿意移动该对象,而非复制它。 C++14为我们提供了一个全新的捕获方式---初始化捕获,也叫做广义lambda捕获,使用初始化捕获,则你会得到机会指定: 由lambda生成的闭包类中的成员变量名字。 一个表达式,用以初始化该成员变量。 例如使用初始化捕获将std::unqiue_ptr移动到闭包内: class Widget { //一些有用的型别 p

王木木 879

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

《Effective Modern C++》学习笔记之条款三十五:优先选用基于任务而非基于线程的程序设计

如果你想以异步方式运行函数doAsyncWork(),有两种方法。 你可以创建一个std::thread,并在其上运行doAsyncWork,这种方式属于基于线程的程序设计(thread_based) int doAsyncWork(); std::thread t(doAsyncWork); 也可以把doAsyncWork传递给std::async,这种策略叫做基于任务(task_based) auto fut = std::async(doAsyncWork); //fut是...

王木木 1071

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

《Effective Modern C++》学习笔记之条款十五:只要有可能使用constexpr,就使用它

constexpr变量必须使用一个具有const属性,且在编译阶段就已知的值对其初始化。例如: int x = 0; const int y = x; //可以使用x对cosnt变量初始化 const int z = 0; constexpr int arraySize = x; //错误,x为运行期间才确定值的变量 constexpr int arraySize = y; //错误,y为运行期间才确定值的变量 constexpr int arraySize = z; //正确,..

王木木 426

《Effective Modern C++》学习笔记之条款十四:只要函数不会发射异常,就为其加上noexcept声明

首先,如果知道一个函数不可能抛出异常,则应该将其声明为noexcept,以提高代码的运行效率,但是如果函数却违法声明抛出了异常将导致程序直接中止。 在C++98和C++11中都可以声明一个函数不会抛出异常,代码如下: int f(int x) throw(); //f不会抛出异常,C++98风格 int f(int x) noexcept; //f不会抛出异常,C++11风格 而使用noexcept而非throw()好处有一下几个原因: 声明为nocept,优化器会对函数做最大值的优化,包括..

王木木 373

《Effective Modern C++》学习笔记之条款七:在创建对象时注意区分()和{}

对象初始化的方式有很多种,特别是C++11新引入了统一初始化,可以用于一切场合的初始化,至少从概念上可以这么理解。目前常见的初始化方式大概有以下几种: int x(0); //使用小括号初始化 int y = 0; //使用等号初始化 int z{0}; //使用C++11新引入的统一初始化格式,即大括号初始化 int z1 = {0};//统一初始化格式变体,编译器对其处理完全无差别 C++11新引入了统一初始化方式可以处理很多C++98无法完成的工作,例如: (1)给一个ST..

王木木 331

《Effective Modern C++》学习笔记之条款五:优先选用auto,而非显示型别声明

废话补多少,直接总结一下使用auto的好处: 1、对于变量未初始化情况,如果使用显示显示型别声明,程序猿将无感知,但是如果使用了auto进行变量声明,将提醒你编译错误。 int x1; //有潜在的未初始化风险 auto x2; //未初始化,编译报错 2、简化代码,特别时迭代器相关的,能够省略很大的代码量 3、对于某些lambda表达式,我们应使用auto变量来接收它,而非std::function,因为无论从效率还是代码整洁度方面,auto都是完胜 //应使用auto而非std::f..

王木木 458

《Effective Modern C++》学习笔记之条款十七:理解特种成员函数的生成机制

这里所说的特种成员函数包括C++98已有的默认拷贝函数、析构函数、复制构造函数、复制赋值运算符以及C++11新增的移动构造函数以及移动赋值运算符。这些特种成员函数在特定场合,编译器都可以自动为其生成,且访问权限都是public的,inline类型的。 以下几点是特种成员函数生成的特点: 仅当一个类没有声明任何构造函数时,编译器才会自动生成默认构造函数。 当基类的析构函数是虚函数时,编译器为子类生成的默认析构函数也才会是虚函数,且析构函数默认为noexcept的。 默认的移动构造函数以及移动赋值...

王木木 372

《Effective Modern C++》学习笔记之条款十三:优先选用const_iterator,而非iterator

在C++98中 const_iterator得到的支持不够全面,使用起来相当费力,C++11对其做了一个很大的优化,但是仍然有死角,但是C++14将这些死角清除干净了,所以现在我们可以很好的使用它。 首先我们要记住的是在C++11中无法将iterator强制转换为const_iterator,即使是static_cast或者reinterpret_cast也不行。 如果我们要获取const_iterator类型迭代器,在C++11中很简单,只需要使用对象调用其成员函数cbegin()或cend()即..

王木木 299

《Effective Modern C++》学习笔记之条款二十八:理解引用折叠

前面我们说过,形参为万能引用型别时,将根据实参的型别来决定最终param的型别: template<class T> void func(T&& param) { //do something } Widget w; func(w); //w为左值,T为Widget&,param为Widget& func(Widget());//实参为右值,T为Widget,param为Widget&& 之所以会有上面结果的推导..

王木木 417
上一篇: Python学习:如何使用pandas分析excel数据(续)
下一篇: Python学习:scapy库的Packet与str相互转换
chaos-god
博客等级 码龄20年 39粉丝 47原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值