[Effective Modern C++] Item 6. Use the explicitly typed initializer idiom when auto deduces undesired types - 当推断意外类型时使用显式的类型初始化语句

条款6 当推断意外类型时使用显式的类型初始化语句

基础知识

  当使用std::vector<bool>的时候,类型推断会出现问题:

std::vector<bool> features(const Widget& w);
// OK
bool highPriority = features(w)[5];
processWidget(w, highPriority);
// ERROR
auto highPriority = features(w)[5];
processWidget(w, highPriority); // undefined behavior

  std::vector<bool>的operator[]操作并不返回一个bool类型,而是返回一个std::vector<bool>::reference(一个std::vector<bool>的内嵌类)。

  存在以上类型是因为std::vector<bool>返回紧凑形式的bool,每一位表示一个bool。vector的operator[]操作返回T&,但是C++静止引用为bit的形式。所以std::vector<bool>的operator[]操作返回一个类似bool&的对象std::vector<bool>::reference,并且隐式转换为bool。

  在使用auto时候,返回可能为一个指针以及偏移量,但随后指向出的内存会被释放,所以highPriority会变成一个悬垂指针(dangling pointer)。

  一些代理类十分明显,如std::shared_ptr和std::unique_ptr,有一些不明显如std::vector<bool>和std::bitset。

  C++中的有些库使用了一种叫做表达式模板(expression template)的技术来提高算术运算的效率。如Matrix + Matrix 返回一个代理类Sum<Matrix, Matrix>。

  在源代码中很难隐藏,所以可以通过以下方式识别代理:

namespace std {
    template<class Allocator>
    class vector<bool, Allocator> {
        public:
            class reference {};
            reference operator[](size_type n);
    };
} // 返回了reference类型

  可以使用显式类型初始化语句(explicitly typed initializer idiom)方式使用auto:

auto highPriority = static_cast<bool>(features(w)[5]);

总结

  • “不可见”的代理类型会导致auto推断初始化表达式时出现错误的类型
  • 显式类型初始化语句强制auto推断为你想要的类型
时间: 2024-10-21 07:33:02

[Effective Modern C++] Item 6. Use the explicitly typed initializer idiom when auto deduces undesired types - 当推断意外类型时使用显式的类型初始化语句的相关文章

Effective Modern C++翻译(7)-条款6:当auto推导出意外的类型时,使用显式的类型初始化语义

条款6:当auto推导出意外的类型时,使用显式的类型初始化语义 条款5解释了使用auto来声明变量比使用精确的类型声明多了了很多的技术优势,但有的时候,当你想要zag的时候,auto可能会推导出了zig.例如,我有一个函数,它以const Widget&作为参数,并且返回std::vector<bool>,每一个bool暗示了Widget是否提供了一个特殊的特性. std::vector<bool> features(const Widget& w); 进一步假设第

[Effective Modern C++] Item 1. Understand template type deduction - 了解模板类型推断

条款一 了解模板类型推断 基本情况 首先定义函数模板和函数调用的形式如下,在编译期间,编译器推断T和ParamType的类型,两者基本不相同,因为ParamType常常包含const.引用等修饰符 template<typename T> void f(ParamType param); // 函数模板形式 f(expr); // 函数调用 存在T的类型即为expr类型的情况,如下T为int templat<typename T> void f(const T& param

[Effective Modern C++] Item 7. Distinguish between () and {} when creating objects - 辨别使用()与{}创建对象的差别

条款7 辨别使用()与{}创建对象的差别 基础知识 目前已知有如下的初始化方式: int x(0); int y = 0; int z{0}; int z = {0}; // the same as above 在以“=”初始化的过程中没有调用赋值运算,如下例所示: Widget w1; // default ctor Widget w2 = w1; // copy ctor w1 = w2; // assignment, operator = 还可以用来初始化: class Widget {

[Effective Modern C++] Item 3. Understand decltype - 了解decltype

了解decltype 基础知识 提供一个变量或者表达式,decltype会返回其类型,但是返回的内容会使人感到奇怪. 以下是一些简单的推断类型: const int i = 0; // decltype(i) -> const int bool f(const Widget& w); // decltype(w) -> const Widget&, decltype(f) -> bool(const Widget&) struct Point { int x, y

Effective Modern C++

1. Deducing Types. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Item 1: Understand template type deduction. Item 2: Understand auto type deduction. Item 3: Understand decltype

《Effective Modern C++》要点中英文对照

目录 CHAPTER 1 Deducing Types 章节1 类型推导 Item 1:Understand template type deduction. 条款1:理解模板类型推导. Item 2:Understand auto type deduction. 条款2:理解auto类型推导. Item 3:Understand decltype. 条款3:理解decltype. Item 4:Know how to view deduced types. 条款4:知道如何查看推导出来的类型.

Effective Modern C++ 读书笔记 Item 1

最近发现了<Effective Modern C++>这本书,作者正是大名鼎鼎的Scott Meyers——<Effective C++>.<Effective STL>的作者. 而就在C++11逐渐普及,甚至是C++14的新特性也进入大家的视野的时候,<Effective Modern C++>一书应运而生.此书与其前辈一样,通过数十个条款来展开,只不过这次是集中于C++11和C++14的新特性.auto.decltype.move.lambda表达式……

《Effective Modern C++》Item 1总结

Item 1: Understand template type deduction. 理解模板类型推导 template<typename T> void f(ParamType param); The type deduced for T is dependent not just on the type of expr, but also on the form of ParamType. 对于T类型推导,不仅依赖传入模板表达式也依赖ParamType的形式. ParamType is

《Effective Modern C++》读书笔记 Item 2 auto的类型推导

注意: 还要学习一个 ↑↑↑↑ 这样的方框里的片段完全不来自于原书,而是我自己的理解. Item 2 Understand auto type deduction - auto类型推导 在C++11之前,auto 关键字一直是用于声明自动储存类型的变量时使用的,基本上没有什么实际作用,地位和 export 关键字(用于向编译单元之外导出模板,也在C++11中被取消)类似. 在C++11中,auto 终于不再废材,终于具备了类似C#中 var 关键字的效果,可以自动推导出变量的类型,可以少打几个字