首先, 我们需要开门见山地指出, 0 和 NULL 都不具备指针类型,
它们的本质是整数,只是依赖于上下文(Context)被“特殊看待”为空指针
0 的类型是 int:它是一个整数字面常量。C++
只是在语言层面做一个不得已的“变通”:仅在上下文强制要求指针的语境中,才将
0
勉强解释为空指针。但在重载决议等情况下,它的“真实身份”——int——会优先被匹配。
NULL 的...
在现代C++开发中, auto
关键字通过要求初始化、正确推导类型以及适应代码重构,避免了许多由于显式类型声明而导致的微妙的正确性和效率问题,
应当作为大部分情况下的首选项来使用。
std::function
std::function 是 C++11 引入的一个非常强大且核心的工具,位于
头文件中。
它是一个通用的、多态的函数包装器。它的核心价值在于,它可以用一个统一的类型来...
虽然 auto
是一个强大的工具(如条款5所述),但它推导出的类型有时会与程序员的直觉或意图不符。这种情况尤其容易发生在涉及“隐形”代理类(proxy
class)的表达式中。
什么是代理类: 在 C++ 中,代理类(Proxy
Class)是一种设计模式的实现,属于结构型设计模式的一种。它的主要作用是为某个对象提供一个替代者或中介,以控制对该对象的访问。这个模式被称为代理模式(...
typeid介绍
typeid 是一个 C++ 内置的运算符(就像 sizeof 或 decltype 一样), 是
C++ 运行时类型识别(Runtime Type Information,
RTTI)机制的核心组成部分。它允许你的程序在代码运行时查询一个对象的动态类型(Dynamic
Type), 当然也可以进行静态类型的查询。
RTTI 并非没有代价(它会给对象增加额外的...
decltype 是 C++11 引入的一个非常重要的关键字. 作为一个类型说明符
(type specifier), 它是 “declared type” (声明的类型) 的缩写, 也是 C++
泛型编程(模板)和类型推导系统中至关重要的一块拼图。
它的核心功能是:在编译时检查一个表达式,并“返回”该表达式所对应的确切类型,但并不会实际计算(执行)这个表达式。
不过在介绍declt...
回忆左值(Lvalue)和右值(Rvalue)
左值(Lvalue)表示一个有名字、可寻址、在表达式结束后仍然存在的对象。其特点是:
可以出现在赋值语句的左边:x = 5;
可以取地址:&x
通常是变量、数组元素、对象成员、函数形参等
右值(Rvalue)表示一个临时值,通常在表达式中短暂存在,不能取地址。其特点是:
只能出现在赋值语句的右边:x = 5;
...
首先我们抛出这一讲的核心思想: auto
类型推导几乎就是模板类型推导,
除了稍后会介绍到的唯一区别之外
两者概念性的转换
这种对应关系可以通过一个概念性的转换来理解。例如,
对于前一讲介绍的函数模板调用:
1234template<typename T>void f(ParamType param);f(expr); // 编译器利用 expr 推导 T 和 Par...
移动语义 (Move Semantics) 和
完美转发 (Perfect Forwarding) 是 C++11
中引入的两个革命性特性,它们共同解决了 C++
中长期存在的资源管理效率和泛型编程(模板)中的参数传递问题。
移动语义 (Move Semantics)
在 C++11
之前,我们只有“拷贝语义”。当我们处理包含堆内存(如指针指向的数据、文件句柄、网络套接字等)的对...
复习初始化语法
在 C++11 中, 进行对象初始化的语法大致可以分为三类: - 使用小括号, 如
int x(10); - 使用大括号, 如 int x{10}; -
使用等号, 如 int x = 10; 当然,
很多情况下也可以使用一个等号和大括号来初始化对象,
如:int z = { o } ;,
下面的讨论我们将忽略这种”等号加大括号“语法,因为 C++
通常会把它和...
如果一个复杂系统的用户对于该系统的运作方式一无所知,然而却对其提供的服务表示满意,这就充分说明系统设计得好。如果从这样的角度来看,
C++的模板型别推导取得了极大的成功。
模板的型别推导,是现代C++最广泛应用的特性之一 ————
auto的基础。也就是说,如果你对C++98
推导模板型别的运作方式感觉满意,那么你也会自然而然地愉快接受C++11 中推导
auto
型别的运作方式...