﻿/*
	© 2012-2014 FrankHB.

	This file is part of the YSLib project, and may only be used,
	modified, and distributed under the terms of the YSLib project
	license, LICENSE.TXT.  By continuing to use, modify, or distribute
	this file you indicate that you have read the license and
	understand and accept it fully.
*/

/*!	\file CommonRules.txt
\ingroup Documentation
\brief 公用规则指定和说明。
\version r2980
\author FrankHB <frankhb1989@gmail.com>
\since build 282
\par 创建时间:
	2012-02-03 16:44:56 +0800
\par 修改时间:
	2014-05-27 13:39 +0800
\par 文本编码:
	UTF-8
\par 模块名称:
	Documentation::CommonRules
*/


/*

@0 前言：

@0.1 体例说明：
（文档专用）外部语义位置标记符：
@ //作用于可打印字符或空白符（见以下定义）的字符序列，表示逻辑位置。
以字符串 @@ 起始的字符串作为外部引用章节。
以字符串 @ 起始的字符串本文档内部引用章节。
以字符 @ 起始的行作为章节标题。
外部文档引用使用 [] 标注。模块名称([Documentation::ProjectRules @@3.2]) 为 Documentation 的引用是 YSLib Project 的正式文档。本行即为示例。

@0.1.1 日期和时间表示：
文本的日期和时间表示基于 ISO 8601:2004 的日期的扩展格式(extended format) 。仅使用精确到日的日期、精确到分或秒的时间，不使用周表示和非完全(complete) 表示。
按 ISO 8601:2004 规定，不在表示内部使用空格。在此约定便于表示解析的例外规则：在表示地方时和 UTC 的差异时使用 ASCII 字符“+”和“-”表示偏差符号，并在此前附加一个空格。

@0.2 限制：
文档引用视为依赖。除 @0.1 和对 [Documentation::NPL] 中的基本概念定义参考引用（“另见”）外，本文档不依赖于 YSLib Project 其它文档。
体例限制为 Unicode(@2.1) 可表示的文本文件。
自然语言为简体中文和英文。
满足以上条件，不限制其它语言使用。

@1 绪论：

@1.1 适用范围：
本文档适用于 Franksoft 一般开发。

@1.1 正式引用：
— ISO/IEC 2382 (all parts), Information technology — Vocabulary
— ISO/IEC 9899:1999, Programming languages — C
— ISO/IEC 9899:1999/Cor.3:2007(E), Programming languages — C, Technical Corrigendum 3
— ISO/IEC 9899:2011, Programming languages — C
— ISO/IEC 9945:2003, Information Technology — Portable Operating System Interface (POSIX)
— ISO/IEC 10646-1:1993, Information technology — Universal Multiple-Octet Coded Character Set (UCS)
	— Part 1: Architecture and Basic Multilingual Plane
— ISO/IEC 14882:2003, Information technology — Programming languages — C++
— ISO/IEC 14882:2011, Information technology — Programming languages — C++
— ISO/IEC TR 10815:2006, Information technology — Programming languages, their environments and system software interfaces — Technical Report on C++ Performance
— ISO/IEC TR 19769:2004, Information technology — Programming languages, their environments and system software interfaces — Extensions for the programming language C to support new character data types
— The Unicode Standard — Version 6.0 – Core Specification
— GCC Coding Conventions(http://gcc.gnu.org/codingconventions.html)

@1.1.1 引用缩写：
 ISO C ： ISO/IEC 9899 ；
 ISO C++ ： ISO/IEC 14882 ；
 ISO C++03 ： ISO/IEC 14882:2003 ；
 ISO C++11 ： ISO/IEC 14882:2011 。

@1.2 术语：

@1.2.1 C++ 语言：

@1.2.1.1
以下列表中的概念参考 ISO C++ ：
翻译单元(translation unit) ：(@2/1 [lex])；
字符集(character set) ：(@2.2 [lex.charset])；
预处理记号(preprocessing token) ：(@2.4 [lex.pptoken])；
记号(token) ：(@2.6 [lex.token])；
注释(comment) ：(@2.7 [lex.comment])；
头文件名(header name) ：(@2.8 [lex.header])；
标识符(identifier) ：(@2.10 [lex.name])；
关键字(keyword) ：(@2.11 [lex.key])；
操作符(operator) ：(@2.11 [lex.operators])；
标点符(punctuator) ：(@2.11 [lex.operators])；
字面量(literal) ：(@2.13 [lex.literals])；
转义[字符]序列(escape sequence) ：(@2.13.2 [lex.ccon])；
实体(entity) ：(@3/3 [basic])；
名称(name) ：(@3/4 [basic])；
作用域(scope) ：(@3.3/1 [basic.scope])；
链接(linkage) ：(@3.5 [basic.link])；
存储期(storage duration) ：(@3.7 [basic.stc])；
类型(type) ：(@3.9 [basic.types])；
对象类型(object type) ：(@3.9 [basic.types])；
不完整类型(incomplete type) ：(@3.9.1 [basic.fundamental])；
命名空间(namespace) ：(@7.3 [basic.namespace])。

@1.2.1.2
以下内容参考 ISO C++ 相关描述：
续行/断行连接(line continuation) ：(@2.1/2 [lex.phases])，“splicing physical source lines to form logical source lines”。

@2 设计的基本原理、表达形式和公用抽象：

@2.1 理论背景、工具和依据：

@2.1.1 计算理论和方法学：
离散数学：集合论、组合数学、图论、代数结构、数理逻辑、范畴论……
设计参考的度量理论：可计算理论、计算复杂性理论。
实现参考的度量理论：略。
面向复用的(reuse-oriented) 需求分析和软件设计。
面向对象分析和设计(OOAD) 。
多范型(multiparadigm) 程序设计：过程式(procedual) 程序设计、结构化(structural) 程序设计、面向对象程序设计(OOP) 、面向接口程序设计。

@2.1.2 开发模式：
按需选择合适的开发策略和工程管理方法。
如果可能，保证以上手段的可复用性。

@2.1.3 架构模式(Architectural Patterns) ：

@2.1.3.1 通用抽象设计：
分层(Layers) ；
外观(Facade) ；
调停者(Mediator) ；
管道和过滤器(Pipes and Filters) ；
解释器(Interpreter) 。

@2.1.3.2 交互式设计：
窗体-控件(Form-Control)；
窗口-图标-菜单-指针设备(WIMP, window-icon-menu-pointing device) 。
模型-视图-控制器(Model-View-Controller) /显示-抽象-控制(Presentation-Abstraction-Control) 。

@2.1.3.3 分布式设计：
暂不考虑。

@2.1.4 设计模式(Design Patterns) ：
略。

@2.1.5 解决模式：
错误处理；
任务安排；
数据验证；
同步请求/响应；
……

@2.1.6 实现模式/代码模式/惯用法(Idioms) ：
语言相关。举例： C++ 的 pImpl 、 copy & swap 。

@2.1.7 其它通用设计要点：

@2.1.7.1 语义冗余：
相对于目标代码的操作语义，源代码表达可以使用指称方法分析的语义，这些语义（例如名称的语义）中的一部分不可避免地无法通过机器表达，而仅供人类参考。
应控制冗余在适量的程度。

@2.1.7.2 内聚与耦合：
代码的内聚与耦合性质作为评价实现的参照而不是目的。
一般意义下，保持代码的高内聚与低耦合有利于维护。但这个结论并非总是适用于可能发生变化的代码。
在一定的局部范围内，内聚可能是不必要的，耦合也可能是必要的。

@2.1.7.2.1 不必要内聚：
内聚表达模块中子模块之间的关联性相关语义。
内聚需要建立在高度抽象的基础上。
在局部问题域发生变化时，子模块之间的关联可能发生变化。此时，维护内聚性可能会导致不必要的成本。
因此，不必维护所有内聚。

@2.1.7.2.2 必要耦合：
耦合表达模块中子模块之间的依赖性相关语义。
耦合可以用于表示代码的修改需要是事务性的：除非替换所有耦合的局部子模块，否则无法保证代码的质量（正确性和可维护性）不下降。
这增加了合理地修改代码需要的最小工作量，但是，并不一定增加总的工作量。整体替换多个子模块可以更容易地暴露它们之间的冗余，降低优化的工作量。
因此，不必消除所有耦合。

@2.2 构建原则：

@2.2.1 人类接口(human interface) ：
本节阐述仅对于人类用户有意义，并不直接体现在运行时的原则。

@2.2.1.1 易用性：

@2.2.1.1.1 简单接口：
接口在合理表述语义的基础上应尽可能简单，具有较小的学习成本。

@2.2.1.1.2 最简名称原则：
在接口中使用最少的名称表达合理的语义。
在实现中尽量少引入不必要的名称。即使是为了适应翻译程序（编译器）的功能限制而不得不引入额外的名称，也需要使用有意义的构词，或者至少给出明确的注释。

@2.2.1.2 明确性：

@2.2.1.2.1 过时(deprecated) 控制：
在正式版本释出的(released) 接口若需要废除，在之前不少于一个的临接版本需要标注 deprecated 提醒库用户接口的变化。

@2.2.2 可移植性相关：

@2.2.2.1 基本术语补充定义：
关于平台无关性（或平台独立性）(platform-independent) 和平台中立性(platform-neutral) ：
一般意义上大致相同，但本文档附加约定：
平台无关性是指代码（源代码或目标代码，下同）在任意现代电子计算机系统（硬件和软件平台）上可以具有一致行为的最大公共实现的特性；
平台中立性是指代码通过一定的软件手段（附加编码、提供附加二进制工具，例如构建虚拟机作为中间平台）实现一致行为的特性。
平台中立性逻辑蕴含平台无关性。平台无关性的条件更严格。

@2.2.2.2 存储架构：
如无附加说明，程序设计使用的默认存储位于基于二进制编址的主存储器。
主存储器寻址的基本单位称为字节(byte) 。一般以整数编址，具有连续取值范围，称为地址空间(address space) 。
处理机中的存储器（寄存器、片内 CACHE ）一般对程序不可见，也不直接按字节寻址。如无附加说明，其它存储器使用和主存储器相同的寻址方式，但编址方式可能不同。
如无附加说明，默认目标平台使用 8 位为一字节。
注意字节序(endianness) ：大端(big-endianness) 、小端(little-endianness) 和 PDP 字节序。平台中立的代码应保证行为不依赖特定字节序。

@2.2.3 可维护性和架构设计：
平衡可复用性和运行期效率。
对于增加复用性导致代码可读性降低的情况，应提供额外注释表明实现细节。
翻译单元（以下简称单元）是语言提供对实现进行部署的基础单位，应合理拆分。

@2.3 通用语义：
本节讨论和约定对于整个程序及其环境通用的描述和一般性结论，也包括契约和其它约束概念。
关于“对象”在 C++ 语言中的概念，参见 ISO C++ Clause 3 。以此为基础推广的意义参见 @2.3.3.3 。

@2.3.1 可编程性和兼容性：
可编程性是程序表达语义的基础。对于通用程序设计，可编程性受到底层实现（例如硬件驱动程序）的约束，仅能够使用有限的接口。
二进制层次上的可编程性在表达语义上无法摆脱底层实现的影响，不利于平台中立的实现，除非有明确说明，不考虑此要求。

@2.3.2 程序模型：
程序模型是具体实现了的架构模式这一结果上进一步抽象的产物，主要从计算机（而不是人类）的角度体现语义表达的一般流程。
在可编程性足够强时，除了实现本身的质量，程序模型几乎只受计算机系统软件（例如语言和操作系统）接口及其实现的约束。
本文档在系统软件领域约定使用以下定义：
程序：有限的指令或其它操作语义方法直接能够表示的内容的集合；
资源：可供计算机系统利用以完成语义表达的实体或信息，可以是硬件或软件；
执行：计算机系统利用资源，使用程序片段实现语义表达的过程；
任务：计算机系统执行特定程序的特定目的。
进程：执行中的程序（一般被作为操作系统调度任务的基本单位）；
线程：进程内部不独占特定资源的最小可执行的调度单位（一般对应于程序设计语言逻辑上的控制流）。

@2.3.2.1 运行时程序模型：
由具体项目定义。

@2.3.2.2 资源分类：
（软件）资源分为（软件）系统资源和应用程序资源。
程序本身是系统资源。
作为任务调度单位的进程和线程是系统资源。
处理器资源是硬件资源，由于并不直接出现在源代码中，不是软件资源，不是系统资源；但若实现环境提供直接接口对其进行操作（例如统计 CPU 利用率）时，视作系统资源。
内存储器是硬件资源，经过语言抽象后转换为地址空间。基于实现的原因，地址空间中某些特定的部分最常被利用，如调用栈上的栈帧。这些资源统称为内存资源。内存资源是系统资源。
外存储器是硬件资源，经过实现环境抽象后以文件系统等形式存在，通过应用程序接口等被进程利用。这些形式中的实体（例如文件）在进程中被映射为特定的数据（例如句柄或描述符），这些资源是软件资源，称为外存资源。外存资源是系统资源。
所有被用于直接维持程序调度相关的资源都是系统资源（例如互斥锁）。
其它资源都是应用程序资源。
和内容相关的应用程序资源称为内容资源，包括文本和二进制资源。
二进制资源按内容使用的形式可以分为程序（此处仅指静态的代码集合）、图形、图像、音频、视频等，也包括其它用户自定义格式的数据。

@2.3.2.3 资源管理：
在特定的时间点或控制流中向进程分配和回收具体的资源实例的行为总称为资源管理。资源管理由进程自身在被执行时实现，其逻辑则由程序员在编译期通过源代码对资源的获取和释放操作条件的描述指定。
资源从使用开始到结束的时间段可以认为是连续的，这和对象有相似之处。
利用 RAII（Resource Acquisition Is Initialization ，资源获取即初始化）惯用法可以把特定的对象和资源实例绑定，此时资源的获取和释放与对象的构造和销毁等价，对象的生存期称为资源的生存期。
对于 C++ 这样支持确定性析构的语言， RAII 直接使 RRID（Resource Reclamation Is Destruction ，资源回收即析构） 或 DIRR（Destruction Is Resource Reclamation ，析构即资源回收）成为可能。这在异常安全(@5.10.5.1) 等方面有重要意义。

@2.3.3 实体(entity) 、生存期(lifetime) 和对象(object) ：

@2.3.3.1 实体：
实体是不加限定的语言的抽象。但一般地，需要能明确两个实体是否同一(identical) 。
关于实体，另见 [Documentation::NPL @@ 2.1.1] 。

@2.3.3.2 生存期：
生存期是逻辑上可用的连续区间的抽象，可以在此之上明确特定逻辑事件的顺序，可用抽象的时刻度量。
关于生存期，另见 [Documentation::NPL @@ 4.1] 。

@2.3.3.3 对象：
某些实体具有能明确顺序且可知开端和终结的生存期，这些实体称为对象。
对象表示状态的集合，占用（抽象机意义的）存储。
关于对象，另见 [Documentation::NPL @@ 4.1] 。

@2.3.3.4 对象的创建(creation) 和销毁(destroy) ：
对象通过创建引入，通过销毁移除。
对象创建完成时生存期开始，销毁开始时生存期终止。

@2.3.3.5 子对象(subobject) ：
特定状态集合作为一个对象的子集，称为这个对象的子对象。
子对象的生存期是所在对象的子集。

@2.3.3.6 实体的复制(copying) ：
实体的复制是以从一个实体为原型(prototype) 引入满足特定比较条件的实体的过程。
对于对象，复制即创建另一个不同的实体。
通常被复制的实体和原型具有某种可被确定的等价关系。
对于对象，这种等价关系可能是存储的值的相等，即按值复制，符合一般按值调用(call by value) 的函数的语言中的参数传递的典型语义。

@2.3.4 实体所有权(ownership) ：
实体所有权 o 是实体的有限集合 E 上的严格偏序关系(strict partial order) o : E → E，简称所有权。
具有所有权的实体集合称为所有者实体集合（以下简称所有者，记作 O ），另一方称为被托管实体集合（以下记作 P ），需满足：
 O ⊂ E ， P ⊂ E ， O ∩ P = Ø 。
因为 o 是严格偏序的，满足反自反、反对称和传递性，它的关系图是有向无环图，称为所有权图。

@2.3.4.1 约定：
当 card(O) = 1 或 card(P) = 1 时，约定可使用其中的唯一元素指代集合本身。
满足 P = Ø 的所有权是空所有权。以下若不另外注明，则“所有权”均指非空所有权。

@2.3.4.2 所有权转移：
所有者的一个所有权被移除，同时另一个实体获得此所有权而成为对应的所有者的过程称为对对应的 P 的所有权的转移。

@2.3.4.3 所有语义和可用性：
所有者负责实现所有语义，即被托管实体的可用性（连续的有效性）的控制。其中最基本的是，实现自身被销毁(destroyed) 时，先行实现对应的 P 的释放(disposition) ，以避免资源泄漏或重复释放。
语言规则可以约定所有权规则。未被任何语言规则保证被托管的实体称为泄漏(leak) ，无法通过语言被访问。泄漏是一种的错误，应避免任意形式的泄漏。

@2.3.4.4 对象所有权和生存期约束：
当实体的所有权中所有者实体和被托管实体都可能是对象。
当两者都是对象时，所有者对象的生存期不晚于被托管对象的生存期开始，不早于被托管对象的生存期结束。
对象对其子对象具有所有权。

@2.3.4.5 实现性质：
由语言特性直接支持，无需显式实现的所有权，称为自动的(automatic) ；除此之外的所有权，称为显式的(explicit) 。
按某些语言的典型语义，一个对象对其子对象（如成员子对象、基类子对象和数组元素）拥有所有权；生存期由语言实现管理的实体托管于语言实现。
这些所有权称为平凡的。平凡的所有权是自动的。
非平凡的且的自动的所有权通过语言提供的作用域机制（附带自动生存期）实现。

@2.3.4.6 独占性：
独占所有权是 O 到 E 上的多值函数，即所有权是一对一或一对多的： O 的所有权是排他的，任意 P 的元素有且仅有一个所有者；但 O 的元素可具有 P 中的多个元素的所有权。
共享所有权是非独占所有权。引用计数对象是典型的实例。
一对一的所有权关系称为基本的。平凡的所有权是基本的。
如无说明，以下仅讨论非平凡所有权，即被托管实体作为对象通过添加对象引用(@2.3.6) 的方式产生的所有关系中的所有权。

@2.3.4.7 条件所有权：
释放资源前需要进行判断的所有权称为条件所有权，用于实现非特定实体之间（如基于引用计数的智能指针和被引用对象）的所有权。

@2.3.4.8 行为限制：
一旦向实体所有者添加了实体，就不应在从所有者移除此实体前通过所有者以外的途径访问此实体（作用于被托管实体，从所有者实体的元素移除元素的操作除外）。
对于 C++ ，由于所有权最终会导致对象被所有者释放，因此具有栈语义的自动对象不宜被添加所有权，否则容易被误释放超过一次。若自动对象被添加所有权，则应确保所有者释放此对象之前，手动从所有者移除此对象。

@2.3.4.9 所有语义和对象释放：
所有语义并不直接体现为操作，而是通过实现中预先定义的策略影响释放行为体现。
对于对象，所有权关系解除时应保证被托管的对象被清理，保证其生存期终止，以免泄漏。一般可以针对特定所有权关系实现特定的释放器或者删除器(deleter) （可以捆绑在所有者的实现中），在释放时执行具体的操作。
通常默认的释放操作是删除(deletion) ，即通过使被托管对象被销毁，其生存期结束确保所有者对此对象的所有权无效（不可用）。

@2.3.4.10 C++ 实现：
所有权关系可以通过自定义指针等任意具有引用语义的对象实现。
可以通过不可共享的（例如 private ） std::unique_ptr 的实例等具有复制构造时所有权转移语义的对象进行简单实现。
所有者可以是多个对象（如引用计数等涉及多对象公共状态策略的智能指针），但通常被托管的对象组只含有一个对象。对于含有超过一个被托管的对象的所有权关系，可以分解为多个所有权关系以简化实现。

@2.3.5 可选值(optinal value) ：
一类对象可以和特定的可选的值关联，作为特定的默认选项或异常状态。
可选值和其它所有非可选值值可通过特定的比较操作区分。

@2.3.5.1 空值(null value) 和可空(nullable) ：
唯一的可选的值可定义为表示特定的状态不存在的空值。
可具有空值的实体是可空的。
特定的可空类型可以增加特定的附加限制和语义。

@2.3.5.2 可选类型(option type/maybe type) ：
可选类型是对接受一个类型参数的参数化多态类型。

@2.3.6 对象引用和引用关系：
对象的存储可以通过直接引用对象自身访问。
除此之外，可以通过一些特殊的实体引用存储，可以是其它完整对象的存储，也可能是未初始化的。
运行期程序资源实例抽象为对象，可以通过其它的实体的使用进行表示。
被直接访问的实体的称为引用实体，被用于表示资源的对象（集合）称为被引用对象（集合）。
两者作为实体，构成一个反自反、非对称、传递的二元关系，称为引用关系。
若无特别说明，以下的引用关系排除传递性，即多次复合引用关系构成的间接引用，而只考虑直接引用。

@2.3.6.1 决定性：
被引用的资源也可以不是运行期决定的程序资源实例，例如静态类型语言中的函数或类的成员。
资源的引用关系可能在运行时改变。

@2.3.6.2 源和目标：
一个引用关系中，引用实体是被引用对象的引用源，简称源；被引用资源是引用实体的引用目标，简称目标；源指向目标。
目标通常只有一个元素。以下讨论主要涉及此情况，结论对于多个资源实例的情况仍然适用。
 @2.3.7 分别讨论几类典型的引用源及其实例。

@2.3.6.3 有效性：
引用关系的有效性依赖于源和目标的确定存在，一旦无法确定双方即无效。
源可能不保持引用状态，无法通过良好定义的操作确定被引用的对象，此时的源称为无效的，如 @2.3.6.11 。
有效的源和无效的源之间可能通过若干良好定义的操作（如遍历操作， @2.3.6.12 ）互相转换。

@2.3.6.4 存储：
对象具有存储，因此资源和存储之间存在一一映射。此时，对象之间的所有权关系即表示对象与资源、资源与资源之间的所有权关系。
引用实体作为对象时，自身也可以具有存储。
关于引用对象在引用存储时可对目标进行附加操作，参见 @2.3.6 中的以下节。

@2.3.6.5 所有权：
若一个源对目标存在独占所有权(@2.3.4.6) ，则源对此资源是独占强引用的。
若一个源和其它源整体对目标存在共享所有权(@2.3.4.6) ，则源对此资源是共享强引用的。
独占强引用和共享强引用统称强引用。
任何非强引用的源或引用关系是弱引用的。弱引用说明源完全没有对目标的所有权。

@2.3.6.5.1 所有权正规化(normalization) ：
注意所有权是严格偏序的，应保证实体集的并得到的所有权关系图没有环，即禁止出现循环引用。在这个过程中弱引用可用于取代直接对所有权取并集造成循环引用的强引用，称为所有权正规化。

@2.3.6.6 透明性和约束：
若能通过一个源直接得到使用语言特性（如 C++ 引用类型以及内建指针类型的内建 * 操作）对目标的访问，则源对此目标及引用关系是透明的。
任何非透明的源或引用关系是不透明的。
引用关系可以具有修饰符约束，仅公开可对进行操作的部分接口。如 const 约束目标不能通过对源的访问进行修改操作。此时引用关系是不完全透明的。

@2.3.6.7 复制：
引用实体可具有复制(@2.3.3.6) 操作。
引用实体的复制的行为可能有以下的常见策略：
深复制(deep copy) ：导致目标的复制且被复制的源具有目标副本的所有权。对于引用对象即按值复制(@2.3.3.6) 。
浅复制(shallow copy) ：目标不因此被复制，保证被复制的源和原有的源指向相同的目标但不具有所有权。
共享复制：在目标复制和指向上同浅复制，但被复制的源和原有的源共享所有权。

@2.3.6.8 转移(moving) ：
引用实体可能具有转移操作。转移操作应不影响目标的生存期和有效性。
引用实体的转移的行为可能有以下的常见策略：
无所有权转移：同浅复制(@2.3.6.7) 。
所有权转移(@2.3.4.1) ：具有强引用的带状态的源（引用对象）在转移操作后放弃所有权，被复制的源指向的原有的源并具有原有的源的所有权。
转移所有权后的引用对象通常具有特定的无效(@2.3.6.3) 状态（如具有空值，参见 @2.3.6.14 ）以和具有所有权的引用对象明确区分。

@2.3.6.9 状态变更：
源可以通过改变自身状态（值）而改变引用关系，例如对源进行赋值操作。
引用实体的所有权转移操作(@2.3.6.8) 是状态变更。

@2.3.6.10 可比较性：
不同的源之间可以定义若干种二元关系运算进行比较。典型的有等价关系（ == ）和偏序关系（ < ）。
源一般是可以比较的。使用等价关系以及非等价（ != ）关系可以判断所给的两个源是否具有相同的可见行为。

@2.3.6.11 间接(indirection) 操作：
间接操作获取具体的唯一目标（通常不直接产生目标的复制；例如始终返回 C++ 内置引用类型或者代理对象），又称解引用操作（ * ）。
当返回 C++ 内置引用或能直接公开目标的操作的类型时是透明的。
可被解引用的源称为可解引用的(dereferenceable) ，这扩展了 ISO C++03 24.1/5 关于迭代器可解引用的定义。
不可解引用的源是无效的。

@2.3.6.12 遍历(traverse) 操作：
改变指向目标的行为的总称。通常至少应包括前向遍历操作（ ++ ）。
源的遍历操作有可能引起无效。

@2.3.6.13 可迭代性：
使源的引用目标在明确的引用目标集合内改变（由间接操作判定，可以确定在迭代后所给的源指向的具体的目标）的操作，称为对源的引用迭代，简称迭代。
一个源当且仅当遍历操作的结果能保证可解引用(@2.3.6.11) 时可有效迭代。
若一个源在经过有限次特定的良好定义的操作（称为迭代操作）后可有效迭代，则此源或引用关系是可迭代的。
任何非可迭代的源或引用关系是不可迭代的。
对于可比较相等（ == ）的两个可迭代的源，若其中之一经过有限次迭代操作后比较相等为真，则后者对于前者是可达的(reachable) 。
迭代器实例作为引用对象可能确定有效性(@2.3.6.3)，它的目标可以视为一个序列(sequence) 。
若确定迭代器对象不和任何序列关联，则迭代器是奇异的(singular) 。可能奇异的迭代器对象是无效的(@2.3.6.3) 。

@2.3.6.14 可空引用：
对于引用对象，扩展 @2.3.5.1 的定义，满足本节以下条件时称为可空的（另见 ISO C++11 NullablePointer 要求）：
可比较相等(@2.3.6.10) ；
可判断有效性(@2.3.6.3) ；
可复制(@2.3.6.7) ；
生存期结束时控制流不中断（析构函数不抛出异常）；
引用指定一个确定的无效状态，具有空所有权(@2.3.4.1) ，此时具有空值。
默认初始化的引用一般具有空值，也可能具有其它未指定的值。

@2.3.7 一般引用源：
关于引用源参见 @2.3.6.2 。
注意一个引用源可以符合以下多种类别。
为了简便起见，实现可能直接按特定类别使用不满足限定条件的引用实例，如使用不满足不透明性的引用对象作为句柄(@2.3.7.5) 。此时不应该依赖于使用受限的操作。

@2.3.7.1 迭代器(iterator) ：
关于“迭代器”的概念，参见 ISO C++ Clause 24 。
迭代器的引用目标是对象（集合，下同）。
迭代器是可迭代(@2.3.6.13) 的。
迭代器一般是弱引用(@2.3.6.5) 的、可浅复制(@2.3.6.7) 的和透明(@2.3.6.6) 的。

@2.3.7.2 指针(pointer) ：
指针是取值为确定有限集的可空(@2.3.6.14) 的引用对象（另见 ISO C++11 NullablePointer 要求）。
指针可能有空值外的其它无效状态(@2.3.6.13) 。

@2.3.7.3 内建指针(built-in pointer)：
 C/C++ 内建指针类型是便于对一般机器存储的抽象(@2.2.2.2) 得到的数据类型，是一般的指针(@2.3.7.2) 的特例和原始含义。
内建指针具有丰富的操作和及严格的限制，若不依赖于具体存储或体系结构，不需要直接使用。
 void* 类型指针引用目标是不确定类型的对象；除此之外，内建对象指针的引用目标是对象（集合）；函数指针的引用目标是非成员或静态成员函数；成员指针的引用目标是非静态成员。
内建指针是语言实现通过地址空间模型实现的引用源，其中对象指针支持算术和关系运算。几乎在所有语言实现中都可以认为是所有引用对象中效率最高的。
内建指针是弱引用(@2.3.6.5) 的：内建指针的生存期和引用目标的生存期无关。
内建指针是透明(@2.3.6.6)的 ：通过 operator* 访问被引用对象。
内建指针是可浅复制的(@2.3.6.7) 和可转移的(@2.3.6.8) ，且转移同浅复制。
 void* 类型以及对象指针是可迭代的：通过 operator++ 等实现迭代操作，且可以通过算术运算实现随机迭代，因此是一种特殊的随机迭代器。
和其它典型指针不同，内建指针默认初始化具有未决定值(indeterminate value) ，不能直接作为有效指针对象使用。

@2.3.7.4 智能指针(smart pointer) ：
智能指针的引用目标是对象或不确定类型的资源（以 void 类型作为目标类型时）。
直接智能指针：强引用(@2.3.6.5) 且透明(@2.3.6.6) 的。
间接智能指针：弱引用(@2.3.6.5) 且不透明(@2.3.6.6) 的，不能直接访问目标，需要通过转换为透明的直接智能指针等方式，对被引用对象间接地进行访问。
智能指针一般是不可迭代的。但是对于目标中存在多个对象（例如目标是包含多个元素的一个数组）时，可以在内部迭代。
作为指针，智能指针允许为无效状态，此时指针是不可解引用的(@2.3.6.11) 和空的(@2.3.6.14) 。
智能指针不一定可以比较或进行指针算术运算，但一般存在用来判断有效性的等效成员 operator bool() 和 bool operator!() ，表现的语义同内建指针在相同操作下一致。

@2.3.7.5 句柄(handle) ：
句柄是引用对象，它的引用目标是对象（不一定是被直接管理的资源）。
句柄可以是强引用(@2.3.6.5) 的，例如对资源进行引用计数。
句柄是不透明(@2.3.6.6) 的：它的值不一定被用户程序明确，可以只通过特定的程序接口访问被引用的资源。
句柄是可复制(@2.3.6.7) 的。
句柄是可转移(@2.3.6.8) 的。
句柄是不可迭代(@2.3.6.13) 的。
句柄一般是可空(@2.3.6.14) 的。

@2.3.7.6 实例：
标准库容器的各种迭代器都是典型的迭代器。
 ISO C++11 标准库的智能指针中， std::unique_ptr 是独占强引用的透明智能指针， std::shared_ptr 是共享强引用的（当引用计数为 1 时退化为独占强引用）透明智能指针， std::weak_ptr 是弱引用的不透明智能指针。

@2.3.8 广义容器和容器(container) ：

@2.3.8.1 广义容器：
广义容器是对确定的实体集合具有所有权的实体的抽象。
满足以下要求的对象称为广义容器：
可空(@2.3.5.1) ；
对其它实体（称为容器的元素）具有独占所有权(@2.3.4.6) ；
深复制：导致元素的对应复制且被复制的容器具有元素副本的所有权；
所有权转移(@2.3.4.1) ：在转移操作后放弃元素所有权，被复制的源具有原有的容器元素的所有权。

@2.3.8.2 平凡容器：
仅具有一个元素或保持为空的广义容器是平凡容器。
可空引用(@2.3.6.14) 是元素为对象的平凡容器。

@2.3.8.3 容器：
容器是可以改变元素数量的广义容器。

@2.4 C++ 对象特性和语义抽象：
本节讨论完成非特定功能但在行为和实现方法上具有显著相似点的某几类对象的性质、意义和行为。

@2.4.1 接口类型：
接口类型是特殊的类类型。接口类型是抽象类，不应被实例化。
接口类型中不含状态（成员数据）；有零个、一个或多个抽象实例方法，但不含具体实例方法。
在 C++ 称为接口类(interface class) 惯用法，使用纯虚函数(@5.13.6.2) 实现抽象方法，仅含有纯虚函数的类就是接口类，可作为此处的接口类型。
同常见的其它语言（如 Java 和 C# ）通过语言特性直接支持的接口类型不同，此处约定的接口类型有以下需要注意之处：
由于实现问题，需要允许析构函数非虚（否则被 odr-used(@5.1.7) 时需要额外定义）；
允许有静态数据域（无论是否是常量）和静态成员方法：注意 C++ 基类的作用域独立于派生类，不影响实现；
允许声明类型，包括 typedef 名称和类类型：注意在 C++ 中的基类作用域和派生类作用域的独立性，以及嵌套类实例不包含外围类实例指针；
允许声明友元；
允许使用访问权限控制：可以包含非 public 成员；
允许空接口被实例化：为了简化接口模板通过宏的实现；注意在 C++ 中，无法把纯虚析构函数的定义放在类的声明内部。

@2.4.2 容器：
容器是在逻辑上包含零个或更多个其它对象的对象。
 C++ 容器是容器实体(@2.3.8.3) 。

@2.4.3 循环迭代器：
经过有限次前置 operator++ 或前置 operator-- 操作，可以得到初始值的迭代器。
理想情况下，通过迭代操作（至少包括前置 operator++ 和前置 operator--）获得的所有临时迭代器状态中，有且仅有一个无效状态。

@2.5 对象通信(object communication) ：
为简化问题，以下讨论默认关于单一程序的运行时映像（进程）内的通信，但实际应用场合可不仅限于本节讨论范围。

@2.5.1 事件(event) ：
事件是一般意义的动作(action) 在程序中的抽象，是一种状态。
通常某种条件被满足时需要产生事件，称为事件的触发。
事件的触发是即时的，包含发生时间和事件内容两个方面的意义。
需要注意，从实现而言，这种即时性是相对的。原因是事件被触发这一动作在实现中需要时间（例如，占用若干个机器的指令周期）。
所以，发生动作时触发事件指紧接动作完成后产生事件在存储器中的映像。例如，“设置控件位置时产生 Move 事件”指紧随试图设置控件位置的后构造 Move 事件的对象（或进入 Move 事件的处理程序等）。这样的行为在逻辑上有确定的顺序。

@2.5.1.1 事件关联对象
特定的事件的触发可能由特定的对象引起，这类对象称为事件的源(source) 或触发器(trigger)。
特定的对象可能对特定的事件的触发作出响应，这类对象称为事件的目标(destination) 或响应器(responder) 。
源和目标之间的关系可以是一对一的，也可能是一对多的。前者的事件是单播事件，后者的事件是多播事件。
多播事件的源又称为发送者(sender) ，目标又称为订阅者(subscriber) 。
事件可以被保存于某个特定的对象中，此对象称为此事件的所有者。

@2.5.1.2 事件空间：
有限的不同种类的事件的集合称为事件空间。
事件空间中以整数或枚举类型标识可以区分不同种类的事件。

@2.5.1.4 事件调用：
事件被触发后引起的响应过程称为事件调用。

@2.5.1.4 事件回调：
事件回调是间接的事件调用。
事件可以在生成同时调用预先设置对应关系（注册，对于多播事件也称为订阅）的事件处理器（事件响应函数），即同步回调；也可以事件发生后延迟调用，即异步回调。
事件处理器可以是对应参数列表的非成员函数或静态成员函数、非静态成员函数和函数对象。
复杂的回调要求事件能够被带有状态地进行传递，此时需要使用带有状态的仿函数。

@2.5.2 简单事件调用：
可以通过把事件本身抽象为具体的类，借用委托（例如函数指针）实现同步回调。

@2.5.3 消息(message) ：
为了传递事件(@2.5.1) 或其它运行时信息，需把其中的事件内容包装至某一可传递的数据结构中。可使用消息机制解决这个问题。
消息（类型）是为了在应用程序进程内部、应用程序进程之间以及应用程序进程和操作系统之间传递数据的一种具体数据结构。它的实例称为消息（Message）。
使用消息传递事件内容，需要包含消息目的指针、主标识和与其语义相关（具体语义可以取决于主标识，也可以由其它指针域的实际类型决定）的其它参数。除此之外，消息类型中的成员是可定制的。
消息对自身各个数据域保持所有权。因此，有必要时，指针域可使用带所有权的智能指针。
各个域完全相等的消息是相等的。除此之外，指针域不等但其内容相等的消息也视为相等。

@2.5.3.1 消息空间：
所有能够在一个处理单元（例如线程）在此单元生存期被处理的消息集合称为消息空间。
除临时对象外，任意完全相同的消息在一个消息空间中不应含有超过一个实例。
消息空间的具体实现可以采用队列等抽象数据结构。

@2.5.3.2 消息队列(message queue) ：
作为消息的容器的一种数据结构，可以一定规则的有序地保存和取出消息。
在消息队列中的消息称为队列消息；其它消息称为非队列消息。

@2.5.4 连接(connection) ：
维持两个实体之间通信关系的状态称为连接。被连接的实体称为端(peer) 。

@2.5.4.1 对等和非对等连接：
需要区分连接两端时，连接是非对等的；否则连接是对等的。
非对等连接中主动提供主要的通信功能实现的实体称为服务端(server) ，另一方称为客户端(client) 。
通常这里提供的功能抽象为传送数据，发送数据的实体是服务端，接收数据的实体是客户端。
注意这里的对等性质不一定是固定的。非对等连接在某一个时刻或时间间隔内可以体现为对等的，例如不进行数据通信。服务端和客户端在特定条件下的角色也可以非固定。
保持对等连接的通信模式称为 P2P （端到端， peer-to-peer ） 通信。

@2.5.4.2 连接对象(connection object) ：
用于表示连接的对象(@2.3.3.3) 称为连接对象。连接对象是对保持连接的资源的抽象。
连接对象至少包含于两端之一。包含连接对象的一端自身可即为连接对象。不包含连接对象的一端在连接建立前可能不存在，而在连接对象初始化时被创建。

@2.5.4.3 连接引用(connection reference) ：
连接引用是引用目标(@2.3.6.2) 为连接对象的引用实体(@2.3.6) 。
连接状态的复制不一定表示连接被有效复制，因此有时需要隐藏连接对象的状态，公开接口中使用对连接对象具有所有权(@2.3.6.5) 的连接引用而不是连接对象。

@2.5.4.4 实例：
连接对象广泛存在于数据通信中。
输入/输出流是保持程序和外部实体（如文件）有序传输连续数据的连接对象。其它实例有保持程序和数据库连接的数据库连接对象、保持程序和网络环境连接的网络套接字对象等。
 ISO C++ 标准库中使用 FILE* 作为连接引用，而不是直接储存状态的 FILE 对象来表示打开的流。

@3 API 设计和风格概述：
 API 的直接用户是程序员。
双关性： API 作为 Application Programing Interface 解释为用于应用程序实现过程中使用的接口；作为 Application Programer Interface 强调使用的用户。
在此保留缩写。

@3.1 基本语义原则：
总体目标：提供合理的抽象。
以下原则普遍地有效约束 API 的语义，以方便用户的使用。

@3.1.1 简单性：
是简单明确的语义的合理表达，使用户能够自然地使用，包括通过组合现有 API 构造衍生接口。

@3.1.2 完备性：
能够完整地实现所有的期望的确定的特性或功能点。

@3.1.3 最小化：
最小接口优先，人本接口作为例程，引导用户使用 API 进行组合。
注意最小接口在确定功能集的前提下和人本接口对比体现意义。

@3.2 基本形式原则：
以下原则约束 API 的形式，避免可用性受用户关于 API 的设计目的的理解的潜在的不利影响。

@3.2.1 直觉化：
尽可能少地依赖用户的特定经验和背景，实现无歧义的语义表达。
不轻易使用和直觉相悖的设计。

@3.2.2 易于记忆：
具有合理的命名和调用风格，使用户容易按照预期目的使用。

@3.2.3 引导易读的代码：
便于编写便于阅读的用户代码。

@3.2.4 相似衍生：
非严格的最小惊讶原则。

@3.3 实现基础：

@3.3.1 API 命名风格：
标识符命名以标识符命名规约(@4) 为基础。
避免命名空间污染，除非是有意耦合的。

@3.3.2 语用规则：
参见 @5 。

@3.4 C++ 实现的广义的契约式设计：

@3.4.1
由于语言的限制，语句（块）级别仅使用断言约束。
注意运行时的断言表达式不应有影响程序可观察行为的副作用，以保证启用与不启用断言的程序之间逻辑的一致性。

@3.4.2 面向接口：

@3.4.2.1
使用接口类型(@2.4.1) 。

@3.4.2.2
可选虚继承，但考虑到性能，应尽量避免。

@3.4.2.3
合理使用接口回调、泛型以及混合实现。
协调接口和抽象类的使用。

@3.4.2.4
关于类型转换，参见 @5.11.4 。

@3.5 抽象构建方法：

@3.5.1 接口设计风格：
最小接口优先。
合理分离接口与实现，减少不必要的接口耦合，尽量避免实现耦合。

@3.5.1.1
涉及类的人本接口应独立于类的定义和实现之外，而不作为成员方法，除非有下列例外。

@3.5.1.1.1 例外 1 ：
方法（特别是被超过一次地）在类的实现中使用。

@3.5.1.1.2 例外 2 ：
非显式地由语法（例如继承和覆盖）约束的相关接口集合（特别是作为不同类中的签名类似的成员方法）。这样可以方便（跨类或跨文件的）重构（目标可能是一个模板）。

@3.5.1.1.3 例外 3 ：
非 public 基类。

@3.5.2 合理封装性：
类不是接口封装的唯一单位。（头）文件可以作为更大粒度的封装单位使用。
使用 C++ 的 pImpl 惯用法(@2.1.6) 辅助封装并分离接口与实现(@3.5.1) 。

@3.5.2.1 封装范围限制实例：
对于以类实例的整体为客体的操作（如 Activate 方法；注意无参数的 Clear 、 Reset 等方法不在此列），除了和对象生存期相关的行为（例如构造、析构和初始化），在翻译单元及命名空间内而不是类的内部封装。

@3.5.3 基于类的(class-based) 面向对象设计：

@3.5.3.1 类作为封装单位：
按需封装类的继承体系，尽可能使用 private 成员而不是 protected 成员。
必要时（例如特定操作符重载，或基于操作名称的自然语义考虑）使用友元突破类的封装性限制。

@3.5.3.2 有限继承性：
使用模块类(@2.4.6) 的多重继承提供实现获得高度可复用性。
仅在必要时使用接口实现。
尽可能使用组合代替 private 继承，除非需要使用派生类覆盖 private 基类的（纯）虚函数或 using 声明基类的成员。

@3.5.3.3 保守多态性：
仅在必要时或可预见的扩展前提下使用虚函数。
尽可能避免虚继承。

@3.5.3.4
除非必要或有可预见的使用场合，使用聚合而不是组合来构建类。

@3.5.3.5
合理地使用类的成员变量保存状态，仅在必要时通过成员函数实现属性。

@3.6 运行期错误处理：

@3.6.1 值语义常规处理：
使用特定的函数返回值（如空指针常量）表示非预期的有效结果。

@3.6.2 异常：
参见 @5.10.5 。

@3.6.3 日志：//E;
输出可选的、可组织的日志文档。

@3.7 模块化设计：
模块是结构性地对程序的划分，可以是指设计时或运行时的。

@3.7.1 原则：
模块应具有适当的封装性。
保证语义正确的同时控制模块之间的依赖性并减少耦合性。
适当使用语言特性和使用规约隔离模块，尽量不依赖实现相关的机制。

@3.7.2 接口规则：
注意模块边界对接口造成的影响。
必要时严格约束交换存储涉及的对象类型满足 trivally copyable(@5.2.2) 。

@3.7.3 插件系统：
有必要时使用插件系统减少解除耦合性。

@3.8 嵌入语言(embedded language) ：
有必要时使用嵌入语言的解释器或即时编译。注意平衡性能和可配置性需求。

@3.9 魔数(magic number) ：
魔数是人为特定选取的固定值，这里也包括字符串内容等。
除非公开地显式约定，不在公开接口（如默认参数）中使用魔数。
除非另有约定或领域逻辑需要（如 UI 中的固定文本），不在异常处理相关实现以外使用魔数。

@3.10 元编程(metaprograming) ：
 C++ 元编程使用特定的语言构造完成编译时计算。
适当使用元编程接口可以节省运行时开销。注意不应使编译开销过分膨胀。
返回类型或编译时确定的值的类类型被作为元函数(metafunction) 。
特征(traits) ，尤其是类型特征(type traits) ，是用于提取特定的编译时信息辅助元编程的一类元函数。
关于成熟的元编程的使用参照 ISO C++11 type traits 和 boost::MPL 。

@3.11 组件和过程语义：

@3.11.1 函数对象(function object) ：
函数对象类型(function object type) 是可以作为函数调用语法的第一个操作数的对象类型；参见 ISO C++11 20.8 。
可调用类型(callable type) 是函数对象类型或成员指针类型；可调用对象(callable object) 是具有可调用类型的对象；参见 ISO C++11 20.8.1 。
调用包装类型(call wrapper type) 是保持函数对象并转发后缀表达式的调用的类型；调用包装(call wrapper) 是具有调用包装类型的对象；参见 ISO C++11 20.8.1 。
注意函数对象类型包括函数指针类型。而函子(functor) 不是 ISO C++ 的正式用词，习惯上专指通过实现 operator() （而不是转换至指针）的类类型函数对象。
以上对象和函数等具有 INVOKE(f, t1, t2, ..., tN) 或 INVOKE(f, t1, t2, ..., tN, R) 的统一后缀表达式调用形式； ISO C++ 要求调用包装可转移构造；参见 ISO C++11 20.8.2 。

@3.11.2 谓词(predicate) ：
使用 bool 类型结果的实体称为谓词，包括非成员函数和成员函数及其引用或调用包装，以及类型特征等元函数。

@3.11.3 非静态成员方法分类：
除了 C++ 特殊成员函数外，一般可以根据是否只读访问对类的非静态成员方法分类。
特定的方法专用于非只读地访问类类型的非静态成员，称为存取方法(mutator method) 或简称存取器(mutator) 。
对应的，只读地访问非静态成员的方法称为访问器(accessor) 。
非只读访问的方法统称修改方法(modifier method) 或修改器(modifiers) ，包括存取器。
非只读访问的方法统称观察者(observers) ，包括访问器。

@3.11.4 设置器(setter) 和获取器(gettor) ：
有时访问器和存取器会被混用（都可同时指只读或非只读访问）导致外延不清，因此有必要约定更明确的设置器和获取器。
习惯上存取器的名称以 set 起始，又称为设置器(setter) ；访问器的名称以 get 起始，又称为获取器(getter) 。关于具体命名，参见 @4.1.7.2 。
不严格使用 C++ 的面向对象特性实现面向对象设计，可以把设置器和获取器推广至类的非静态成员函数范畴之外，只要保证 INVOKE 调用形式(@3.11.1) 等价即可，实际语义为：
设置器修改某一个特定对象的特定子对象；
获取器取某一个特定对象的特定子对象或其 const 引用。
注意返回 bool 类型的获取器是谓词(@3.11.2) 。因此含义清楚时，排除元编程用途的谓词可以专指返回ool 类型的获取器。

@4 基于类 C 语言的标识符命名规约(naming convention) ：
标识符的长度应不大于 ISO C++ Annex B 约定的实现支持的标识符包含字符数的最小值 1024 。
以下是默认风格标识符的命名规则和约定。

@4.1 通用指引：

@4.1.1 原则：
接口一致性：相同接口的命名风格应保持一致。
上下文一致性：尽可能保持上下文命名风格的类似性。
推论：在完善的设计中，若在一个代码片段中存在不同风格的代码，则这些代码不属于同一套接口。
注意：需要存在多套接口的情况下，可能会隐藏潜在的接口设计的不完善性。

@4.1.2 适用范围：
基本例外：
类的 private 成员、不在函数原型中出现的函数声明中的形式参数名称、函数中的块作用域（注意不包括属于函数声明作用域的形式参数列表）、函数作用域（仅限标签名称）和未命名命名空间中的名称不受本规约限制。
经过约定的全局名称可不受本规约限制。

@4.1.3 拼写和构词原则：
基于兼容性考虑，不使用基本字符集（不另外声明默认为 ASCII ）以外的 Unicode 字符。
以美式英语作为命名标识符的基本自然语言参考。
使用 ISO C++ 术语拼写。其它术语使用兼容于 GCC Coding Conventions 的术语拼写。剩余术语规范见下文。
若不使用以下构词原则或例外，至少应在原始声明处注释。

@4.1.3.1 基本构词原则：

@4.1.3.1.1 缩略词：
一般除了习惯（例如使用 GUI 表示 Graphic User Interface ），不构造新缩略词。

@4.1.3.1.1.1
被缩写词大小写不改变。
如“GUI”缩写后不作“Gui”。

@4.1.3.1.2 非缩略词和一般词组：
词与词之间需有 "_" 分隔符或大小写不同以示区分。除了 @4.1.3.1.3 中的情况外，通常使用后者。
单词的首字母大写，其它字母保持原形式（通常为小写）不变。
多个单词连用，保持首字母大写，省略其中空格。
这里的单词应是自然语言中较广泛使用的单词，若存在多种拼写方法，使用较常见形式，特别是语言标准中已经有定义的概念（如使用“adaptor”而不是“adapter”）。

@4.1.3.1.3 专有名词例外：
对于某些专有名词不受以上限制（除了仍然受语言实现字符集限制）。
例如“GB”（“国标”的汉语拼音缩写）。

$4.1.3.1.4 临时性例外：
例如兼容性考虑的类型名可以全部大写。应注释说明。

@4.1.3.2 框架级名称：
对于公开的可能具有二进制互操作性（需要有限保证二进制兼容性）的接口名称（符号），无论是类名、模板名或函数名，无论是否是成员，都应使用大写字母起始的名称。
其它名称无此限制，但应避免非框架级名称与之混淆，例如可以使用 C++ 标准库兼容构词方法(@4.1.3.3) 。
（宏名是预处理符号而不是符号，不适合此命名约定。）

@4.1.3.3 非框架级通用名称：
使用以下的兼容 C++ 标准库风格的构词方法。
使用语言支持（如 range-based for 依赖的 begin 和 end ）、标准库或类似标准库命名风格的通用库（如 Boost ）时，除模板形式参数外的对应实体名称的命名使用库的命名风格，以便保持模板内部名称的兼容性和适当的上下文一致性(@4.1.1) 。
注意对于如“valarray”这样的惯用名称，视为单词（非专有名词）而不是词组。因此“ValArray”不是“valarray”对应的默认风格名称。由 @4.1.3.1.2 ，只能保持原文，或者使用同义词组按 @4.1.3.1.2 所述方法得到的“ValueArray”代替。

@4.1.3.4 简单非框架级名称：
在不致混淆的情况下，单字母等（可能是在其它情况下的简单前缀）可以直接作为约束变量（哑变量，如循环变量）或形式参数名称。
下划线和数字组合的名称用于特定模式的参数，类似 std::placeholders 中的公开接口的名称。

@4.1.3.5 其它非框架级名称：
无特殊限制。
模板形式参数可与框架级名称约定一致。

@4.1.3.5 前缀命名法：
慎用前缀。

@4.1.3.5.1
不使用小写字母起始的驼峰命名法（ lowerCamelCase 风格），以免和可能使用的习惯匈牙利命名法的名称(@4.1.3.5.3) 混淆。

@4.1.3.5.2
在有限的类型或模板参数命名场合需要使用变形的系统匈牙利命名法，如 @4.3.5.2 。

@4.1.3.5.3
除了类的 public 成员外，对象命名可以使用习惯匈牙利命名法。

@4.1.3.5.4
起始两个大写字母，之后紧接小写字母的类型（此上下文包含参数化类型，下同）标识符，第一个字符会被作为类型前缀。

@4.1.3.5.5
少数特例(@4.3.5.2) 中，出现在类型标识符起始则被视为既定的类型前缀组合。
一般应避免出现起始两个大写字母，之后紧接小写字母的非前缀标识符，以免混淆。

@4.1.4
在同一作用域中可以使用同一名称表示类型和对象。
（此时引用类型名须使用命名空间限定，否则无法正确编译。）

@4.1.5
语义：函数名以谓语动词（不一定是原型）起始。
成员函数名以动词起始，其它成员不使用谓语动词起始，以示区别。

@4.1.5.1
例外：参见 @4.1.3.1.3 ，如 C/C++ 标准库扩展函数。
为保持风格一致，不使用以上命名规约。

@4.1.6 保留标识符：
一般不应被用户程序使用。
由具体项目定义。

@4.1.6.1 语言相关的默认限制和使用：
参见 @5.3.2.3 的名称限制，除非另有说明。
 ISO C++ 内建特性相关的名称使用见 @5.3.4 。
其它参见 @4.1 以下小节。

@4.1.7 惯用命名：
优先使用以下命名。

@4.1.7.1 原语(primitive) ：
动词原型表示的具有合理自然语义的操作，通常对于用户程序来说是原子的(atomic) ，不通过任何进一步的接口名称拆分加以解释。
包括以下名称：
 Activate ：激活（设置激活状态）。
 Clear ：清除（置参数的主要内容为特定状态；一般置为初始状态）。
 Close ：关闭（释放资源，取消资源使用状态）。
 Copy ：复制（按指定对象构造相等的新对象）。
 Deactivate ：取消（取消激活状态）。
 Delete ：删除（销毁参数指定的对象）。
 Draw ：绘制（光栅化自身或目标对象）。
 Flush ：刷新（刷新对象状态，完成刷新后应保持指定目标和自身同步）。
 Merge ：合并（按大于一个非特定类型对象的引用或值参数构造包含所有参数值的对象）。
 Open ：打开（获得资源，设置资源使用状态）。
 Paint ：绘制（按特定条件完成自身或目标对象的各个组成部分的光栅化）。
 Print ：打印（以特定方式输出）。
 Refresh ：刷新（刷新对象状态，完成刷新后应保持自身和由自身状态决定的目标同步）。
 Reset ：复位（置参数的值为默认状态；一般置为初始状态）。
 Release ：释放（参数作为对象或对象引用）。
 Swap ：交换（参数作为对象或对象引用）。
 Update ：更新（完成参数的特定同步操作）。
注意需要配合使用标准库（进行 ADL(@5.3.3.1)）时，使用 swap 代替 Swap 。尽管不使用 ADL ，为保持一致性，成员函数与之对应也使用 swap 而不是 Swap 。
表示清除容器时，使用 clear 而不是 Clear ，以便满足标准库容器要求。

@4.1.7.2 模式(schema) ：
具有一定规则的名称组合方式表达同类含义（作为前缀的通配符表示的字符串包含作为操作名称的非空前缀；操作名称默认为动词原型，可以是原语(@4.1.7.1) ）。
包括以下名称：
 *From ：操作名称起始，第一参数指定源的函数。
 *Ptr ：指针（类型为内建指针类型或智能指针类型）。
 *Ref ：引用（类型为非 const 引用类型，除 *RRef 外为左值引用类型）。
 *RRef ：右值引用（类型为非 const 右值引用类型）
 *To ：操作名称起始，第一参数指定目标的函数。
 Be*With ：* 为操作名称过去分词（被动语态）；按参数完成特定操作达成特定状态。
 Get* ： * 不以 Of 结尾，为目标名称；取特定目标的获取器(@3.11.4) ；通常是 const 非静态成员函数或模板。
 Get*Of ： 同 Get* ，但通常为非成员函数或模板，第一参数为目标操作对象的 const 引用。
 Is* ： * 为目标名称；谓词：计算目标状态，返回类型为 bool 的结果。
 Set* ： * 不以 Of 结尾，为目标名称；修改特定目标的设置器(@3.11.4) ；通常是非 const 非静态成员函数或模板。
 Set*Of ： 同 Set* ，但通常为非成员函数或模板，第一参数为目标操作对象的非 const 引用。
 On* ： * 为描述事件及事件响应目标的名称；事件处理器。

@4.1.7.3 ISO C++ 标准库惯用命名：
包括以下成员类型名：
 size_type ：表示元素数的无符号整数类型；
 difference_type ：表示差值的有符号整数类型；
 iterator ：迭代器类型；
 const_iterator ：只读迭代器类型；
 pointer ：指针类型（注意作为删除器的成员类型可影响 std::unique_ptr 的 pointer 成员类型）；
 reference ：引用类型。
包括以下成员函数名：
 begin ：表示起始迭代器。
 end ：表示终止迭代器。
 at ：带有越界检查的访问函数，接受一个左值引用类型的参数，越界时抛出异常（如 std::out_of_range ）；参见 ISO C++ [sequence.reqmts] 和 ISO C++ [associative] 。
 swap ：交换函数，接受被交换的左值引用类型的参数，返回类型 void ；参见 ISO C++ [swappable.requirements] 。
包括以下命名空间作用域函数或函数模板名：
 to_string ：转换为字符串（通常应为 std::string 类型或至少类型名为 string ）表示。
 make_* ：返回特定对象的助手函数（模板）。
 swap ：交换函数。
包括以下 ISO C++11 成员函数名：
 cbegin ：表示起始只读迭代器。
 cend ：表示终止只读迭代器。
包括以下 ISO C++11 命名空间作用域函数或函数模板名，参见 ISO C++ [stmt.ranged] ：
 begin ：用于 range based for 的起始迭代器。
 end ：用于 range based for 的终止迭代器。
包括以下可能用于 ISO C++1y 命名空间作用域函数或函数模板名：
 cbegin ：用于 range based for 的起始只读迭代器。
 cend ：用于 range based for 的终止只读迭代器。

@4.2 宏名：
保留项参见 @4.1.6 。

@4.2.1
默认使用大写字母。用其它标识符构造的宏以及特殊宏除外。

@4.2.2
特殊宏。

@4.2.2.1
实现语言功能，如interface等。

@4.2.2.2
代码生成器：用宏展开为一段声明或定义的代码。

@4.3 类型名：

@4.3.1
定长整型：全局命名空间中的类型，以前缀和字长组合的形式以明确整型所占的空间。前缀 s 表示有符号整数，前缀 u 表示无符号整数。

@4.3.2
通用类型：非全局命名空间中的类型，小写字母，以 "_t" 作为后缀。

@4.3.3
聚集(aggregate) 类型：数组或容器类型，用不少于2个大写字母和后缀 "s" 组成。

@4.3.4
通用模板类：小写字母，词之间以 "_" 分隔。

@4.3.5
保留类型前缀（关于类型前缀，详细参见 @4.1.2.2 和 @2.4 ）：

@4.3.5.1
全局专有模板类前缀 G(Global Generics) 。可和其它前缀共用。

@4.3.5.2 类型特性划分：
部分使用系统匈牙利命名法。以下前缀适用于 struct 和 class 类型。
非类型参数化的类型前缀（即除了 G 以外的前缀）至多使用两个。
类型特性参见 @2.4 。

@4.3.5.2.1
接口（纯虚类）前缀 I(Interface) 。
对应的接口模板前缀 GI 。

@4.3.5.2.2
包含默认实现语义的虚函数的非严格接口（实际为抽象类）在此也作为接口处理。

@4.3.5.2.3
抽象类前缀 A(Abstract) 。
对应的接口模板前缀 GA 。

@4.3.5.2.4
静态类前缀 S(Static) 。

@4.3.5.2.5
模块类前缀 M(Module) 。

@4.3.5.2.6
句柄类前缀 H(Handle) 。

@4.4
标号：同通用模板类(@4.3.4) 。

@4.5 函数名：

@4.5.1 非成员函数：
以命名空间区分，长度不少于2 。

@4.5.2 成员函数：
除 @4.5.1 限制外， public 函数首字母须大写。

@4.5.2.1
 "Get" 和 "Set" 起始的类的成员一定是成员函数；不一定为类的访问器，但须符合访问器的一般语义。

@4.5.2.2
一般不使用缩写，除非有特殊含义。

@4.5.2.2.1
 "N" 表示索引或总数。

@4.6 具名对象：

@4.6.1
 const 对象首字母大写，除非是局部（函数体或以下级别）的临时性常量。

@4.6.2
静态 public 成员首字母大写。

@4.6.3
逻辑上包含同质(homogeneous) 元素（典型情况是包含相同类型的对象）的聚集(aggregate) 的变量名具有后缀 "s" 。

@4.6.4 哑(dummy) 变量：
不超过 2 个小写字母组成。

@4.6.5 其它变量：
不限制。一般同标号。

@5 C++ 语用学：
本节表述具体设计内容无关的源代码特性使用和编码风格。

@5.1 概述：
相关概念参见 ISO C++11 Clause 1 。
若实际代码与本章的规则不一致，则应以文档或代码附近的注释显式说明不遵守的充分理由。

@5.1.1
禁止程序引起未定义行为(undefined behavior) 。
注意使用未初始化对象具有未决定值(indeterminate value) 。读取未初始化对象的值引起未定义行为。
禁止接口行为依赖于未决定值。

@5.1.2
避免程序的结果依赖于引起未指定行为(unspecified behavior) 的特性。
禁止接口行为依赖于特定的未指定行为。

@5.1.3
需要使用引起实现定义行为(implementation-defined behavior) 的特性时，适当注释。
禁止接口行为依赖于特定的由实现定义行为，除非存在显式的接口使用约束（同时给出注释）。
注意 ISO C++ 中，实现定义行为不是未指定行为的子集，这点和 ISO C 不同。

@5.1.3.1 例外：
可以有少数不显式注释即使用或依赖于通用的实现特性的例外，在这里列出：
对于预处理指令 #include " q-char-sequence" new-line ，假定从源文件的当前路径开始搜索包含项。

@5.1.4
慎重使用有条件支持的(conditionally-supported) 特性。

@5.1.5
禁止使用 ISO C++03 Annex D 中的 deprecated 特性，除以下有说明外；
避免使用 ISO C++11 Annex D 中的 deprecated 特性。
注意以下在前者在前者中作为 deprecated 特性，在后者中被删除（重新支持）的特性，除非必要应避免使用：
 ISO C++03 Annex D.2 static keyword [depr.static] 。
（参见 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3296.html#FI6 。）
应特别注意禁止使用在前者中作为 deprecated 特性，在后者中不支持的特性：
 ISO C++03 Annex D.3 Access declarations [depr.access.dcl] ；
（参见 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3296.html#US56 。）
 ISO C++03 Annex D.4 Implicit conversion from const strings [depr.string] 。
有限使用动态异常规范，参见 @3.6.2.6 。

@5.1.6
注意规避当前语言标准未解决的问题。例如：
 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232 ，截至 ISO C++11 出版仍是草案状态，通过内建下标操作访问（但不使用值） one-past-end 指针不能确定引起未定义行为（但 ISO C99 中已明确不是）。
上述情况下应该使用指针加法代替下标操作。

@5.1.7 正确性：
合式的(well-formed) 程序遵照三个规则：语法规则、可诊断语义规则和 ODR（One Definition Rule ，唯一定义规则）。
形式非法的(ill-formed) 程序是非合式的程序。
注意一个合式的程序可以包含未定义行为。此时程序不是正确的可移植的程序。
特别注意一个实现虽然一般应拒绝并没有被限定形式非法的程序，但有“不要求诊断”(no diagnostic required) 的情况下除外。
 ODR 对于不同的实体(@5.2.1) 的特定使用（称为 odr-used ）具有不同的要求。参见 ISO C++ 3.2 。

@5.1.8 C++ 存储模型：
 C++ 讨论的内存(memory) 明确排除不可按字节(@2.2.2.2) 寻址的存储。一般被实现为主内存。

@5.1.9 C++ 对象模型：
对象具有生存期(lifetime) 和存储期(storage duration) 。
对象具有类型(type) 。
非类类型对象或最终派生类(most derived class) 类型的对象是最终派生对象(most derived object) 。
除了位域(bit-field)，最终派生对象保证占用连续的非零存储单元。一般首个单元对应的即表示对象存储的地址。
不同的对象占据不同的存储单元的完整对象具有不同的地址。

@5.1.10 程序执行：
 ISO C++ 使用抽象机描述程序语义，但不要求实际实现与之完全一致。至少遵循的语义包括对 volatile 对象的访问、程序终止状态和可被动态观察的输入和输出对应的行为，称为可观察行为 (observable behavior) 。
实现的语义遵循 as-is 规则：不影响可观察行为的程序行为可以被实现改变。这是可被允许的一般的优化的根本依据。
表达式的求值(evaluation) 一般意义上包括值的计算(value computation) 和产生副作用(effect) 。
副作用包含对 volatile 对象的访问、对对象的修改和使用 I/O 库函数，表示对环境的改变。
求值的顺序并不一定被确定。任意两个求值之间具有先序(sequenced before) 、不确定有序(indeterminatly sequenced) 或无序(unsequenced) 二元关系之一。
在同一个对象上的无序求值引起未定义行为。

@5.1.11 多线程执行(multi-thread execution) 环境和数据竞争(data race)：
实现可能允许一个程序具有多个并发执行的执行线程(thread of execution) ，简称线程(thread) 。
线程对对象的访问之间可能具有不确定的关系。当无法确定值时产生数据竞争，程序具有未定义行为。使用恰当的同步(synchronization) 避免数据竞争。

@5.2 基本概念及语义：
参见 ISO C++11 Clause 3 和 Clause 5 。注意与 ISO C++03 的区别。

@5.2.1 名称和实体：
区分名称和实体。
注意链接是名称而非实体的属性，尽管也用于命名空间(@5.5.8) 。
关于名称的使用，参见 @5.3.2 。
明确声明引入名称，定义和实体的存在直接相关。
明确定义是声明，但声明不一定是定义。参见 ISO C++ 3.1 。

@5.2.2 对象、变量和值：
对象和变量都是实体。
区分对象和变量。
对象表示存储。
明确变量是通过声明引入的对象。变量具有对象或对象引用类型。
对象具有存储期和生存期。
注意对于非 trivial 构造/析构的对象，生存期始于构造结束，终于析构开始。
注意静态对象的生存期。
注意 POD 对象（包括 ISO C++03 和 ISO C++11 的不同定义）、标准布局(standard layout) 类型对象和 trivially copyable 对象，以及它们之间的区别。
注意非 standard layout 或 trivially copyable 对象的使用限制（和 C 存储的交互性， std::memcpy 、 offset 的适用性等）。
了解 scope guard 等和对象生存期相关的惯用法。
值(value) 是由实现定义，没有其它约定的实体。
一个对象的对象表示(object representation) ，以其存储被 N 个 unsigned char 对象连续表示体现，其中 N 等于对象的大小。
一个对象的值表示(value representation) 是特定位的集合，能决定特定的值。因此对象具有存储值(stored value) 。

@5.2.3 值类别(value category) ：
注意值类别是表达式的属性。
注意区分 lvalue 、 xvalue 和 prvalue 。
注意右值引用为 xvalue 的条件。
注意函数表达式的值类别。

@5.2.4 类型(type) ：
 C++ 的类型包括 void 类型、对象类型、函数类型和引用类型。
注意类型可被限定符修饰，限定符可影响类型，参见 @5.6 。
类型关键字、静态类型推导（模板以及 C++11 关键字 auto 和 decltype ）参见 @5.7 。

@5.2.5 对齐(alignment) ：
对象类型具有对齐要求(alignment requirement) 。
对齐(alignment) 是实现定义的整数值，表示相邻分配对象的最小地址间隔。

@5.2.6 表达式及其求值(evaluation) ：
基本概念参见(@5.1.10) 。
注意非求值操作数(unevaluated operands) ，其中不发生求值，没有副作用。
注意内建表达式和重载操作符约定的值类别(@5.2.3) 的差异。
注意函数类型等价性，尤其是讨论重载时；参见 @5.12.1 。

@5.3 词法、预处理和内容无关的上下文编码规则：

@5.3.1 源代码文件和字符：
必须保证源代码文件使用的字符集可被实现接受并正确处理（兼容于基本源字符集和基本执行字符集）。
禁止源文件的注释以外部分使用 Unicode 控制字符。
不使用双联符(digraphs) 和三连符(trigraphs)。
行末必须保留至少一个换行符以保证不引起未定义行为。
不过度依赖词法分析的贪婪性。对于多个连续的操作符，必须以无误导性的方式使用空白符分隔。
例如，避免二元/和一元 * 连用导致错误的注释起始标志。

@5.3.2
名称使用限制参见 @5.15.1 。

@5.3.3 名称查找(name lookup) ：
注意查找顺序。
 using 关键字的使用参见 @5.5.7 。

@5.3.3.1 参数依赖查找(argument dependent lookup, ADL) ：
当需要禁止 ADL 时可以使用限定名称或带小括号的名称代替非限定名称。
注意当非限定名查找类成员、非 using 声明的块作用域名称或非函数（模板）名称后 ADL 查找关联名称为空。
不使用冗余的限定名，但需要突出所在的作用域时除外（例如使用带有前缀 :: 的全局名称以便和其它命名空间的名称区分）。

@5.3.3.2 依赖名称：
类模板中，显式使用 this 启用依赖名称(dependent name) 的名称查找。
若不需要依赖名称，不使用 this-> 等形式引用名称，以避免可能的错误引用和编译性能下降。

@5.3.4 标识符命名风格：
以下讨论内建特性相关的名称。其它参见 @4 。

@5.3.4.1 range-based for ：
 begin 和 end 被 range-based for 使用。

@5.3.5
其它编码风格参见 @6 。

@5.3.6
有源代码兼容性和可读性良好替代方案的情况下，尽可能不使用宏。

@5.3.6.1
尽可能使用 constexpr 关键字而不是宏定义常量。
尽可能使用 const 关键字定义只读对象。

@5.3.7
使用条件编译控制文件包含，而不是编译器相关的非标准预处理指令（例如 #pragma_once 和 #include_next ）。
除此之外，尽可能不使用条件编译。

@5.3.8
可以使用 #error 、 #warning 和 #line ，但没有确定环境支持时，仅使用基本字符集的字符，以免出现不符合的预期文本。
对于 #error 提示用户的文本内容，一般尽量使用字符串字面量而不是直接的记号序列，以完整地表达含义且便于搜索。

@5.3.9
对于 #include 指令，使用 <文件名> 或 <相对路径> 表示外部库依赖项（仅允许头文件）， "文件名" 或 "相对路径" 表示内部库依赖向（特殊情况下允许源文件，但需在文档中说明目的）。
关于搜索路径，另见 @5.1.3.1 。
在非正式测试等临时用途以外的情况下不使用绝对路径。

@5.3.10
一般应允许使用 #pragma STDC 。
避免 #pragma 后的标识符被作为宏替换为非空记号，以免由实现定义的行为导致的差异。
其它使用 #pragma 的情形由具体项目定义。

@5.4 替代表达保留字(alternative tokens) 、转义字符序列和字面量：

@5.4.1
一般不使用替代表达保留字，以避免导致被替代的标点不够清晰。

@5.4.1.1 例外：
使用 and 和 or 代替内建操作符 && 和 || 以向读者强调对于预期的程序逻辑，两个操作数的求值顺序可被交换（注意 C++ 语义仍然一致）。

@5.4.2 转义字符序列：
使用正确、无歧义的转义字符序列。
注意被转义的字符和基本源字符集之间的关系。
仅在必要时使用八进制或 Unicode 转义字符序列。

@5.4.3
关键字 true/false 和 bool 类型对应；宏 TRUE/FALSE 和 int 类型（例如自定义的 BOOL 类型）对应。
除非有必要，仅使用前者。
另见 @5.11.6 。

@5.4.4
非关键字字面量的表达必须保证符合语法，且兼顾可读性。

@5.4.5 零值：
整数用0，浮点数用 0.0 。
空指针用 nullptr （考虑 C 兼容性可以在保证定义正确的前提下使用 NULL ）。
字符（串结束符）用 '\0' 或带前缀的 L'\0' 等表示（其它可选的非字面量的表示形式：对于字符类型 T 使用 T() ； 使用自定义宏 NUL ）。
有必要使用 float 时，用 0.f 。
 bool 类型以外的整数类型零值和 false 可以互相转换。另见 @5.11.6 。

@5.4.6
合理使用字符串字面量前缀（'L' 、 'u8' 、 'u' 、 'U' 、 'R' 及其组合）。

@5.4.7
可以使用字符串字面量初始化 C 风格字符串。
被初始化的若为字符数组，元素（字符类型）必须是 const 类型修饰的，参见 @5.1.5 。

@5.5 声明和命名空间：
注意区分涉及声明的语法歧义，参见 ISO C++11 6.8 。
注意函数声明和函数定义的区别。

@5.5.1
不使用表示存储类的关键字 auto ，使用编译器的隐式实现。
显式使用会使和 ISO C++11 代码的共用出现问题。

@5.5.2
尽量避免使用存储类关键字 register ，参见 @5.1.4 。
除了平台相关的上下文以外，不使用 register 。
注意 register 仅是建议，而不是命令。

@5.5.3
尽量避免使用静态和全局存储期对象。

@5.5.4 static 和 thread_local ：

@5.5.4.1 命名空间作用域 static ：
注意命名空间作用域的 static 修饰的声明的名称具有内部链接。
避免使用 static 在命名空间作用域声明对象，参见 @5.1.5 以及以下讨论；除非明确需要内部链接且使名称满足特定于实现的需求。
使用翻译单元内的适当的若干未命名命名空间代替，以便自由选择使用内部链接或外部链接，且允许使链接作用于类类型或 typedef 名称等的声明；参见 @5.5.8.1 。
注意 ISO C++03 要求模板非类型实际参数要求名称具有外部链接，参见 ISO C++03 14.3.2/1 ；此时 static 不再适用。但是， ISO C++11 明确命名空间具有的链接(@5.5.8) ，同时也取消了这个限制，参见 ISO C++11 14.3.2/1 。
因此在 ISO C++11 实现中， static 仍然可用，但可能造成混乱，所以避免使用。
为了一致性，一般同时使用未命名命名空间代替命名空间作用域内的 static 函数。
若需要命名空间中声明的名称具有内部链接，可以使用嵌套未命名命名空间(@5.5.8.1) 。但是，现代的实现一般使用 as-if 规则对二进制代码进行优化，它不改变用户程序的可观察行为，所以这种用法并非必要。

@5.5.4.2 类作用域 static ：
注意类作用域 static 用于修饰成员声明，指定其为静态成员，决定其不依赖具体对象。
除非必要，否则不依赖于 this(@5.7.5) 的成员应该为静态成员。
对于成员函数，在类的定义中直接使用 static ，不在类的成员函数定义中重写。
 const 或 constexpr 静态数据成员可直接在类定义内初始化。在没有被 odr-used(@5.1.7) 时不需要定义。这是初始化且不引入定义的唯一特例（关于声明和定义，参见 ISO C++ 3.1 ）。

@5.5.4.3 块作用域 static ：
注意块作用域 static 用于修饰声明的对象，决定其具有静态存储期。

@5.5.4.4 thread_local ：
在可以且有必要使用 thread_local 时，不使用 static 代替。
注意可能和 static 同时使用。
注意 thread_local 允许动态初始化，而实现提供的类似扩展特性可能不允许。
注意对应于 ISO C11 的标识符 thread_local 不是关键字，而以宏形式在标准库头文件 <threads.h> 引入，对应关键字是 _Thread_local 。

@5.5.4.5 和其它关键字连用：
注意 ISO C 中的存储类关键字并不在最前的函数声明被 future language directions 标注为过时。使用如 inline static 的声明，可能引起某些编译器的警告。
在 C++ 代码中一般习惯保持相同的使用顺序。

@5.5.5 extern ：

@5.5.5.1
正确地使用 extern ，并检查语义的合理性。
注意对于之前已有的对象声明， extern 不能直接决定其链接，必须参照之前的声明。
不使用冗余的 extern 。

@5.5.5.2
在多个翻译单元中，extern 声明的类型应保持一致。

@5.5.6 内联 ：

@5.5.6.1 语法：
在必要时使用 inline 关键字。
不使用冗余的 inline （类模板的成员不适用）。
 inline 对于 namespace 的使用参见 @5.5.8.3 。
使用 static inline 而不是 inline static ，使用 thread_local inline 而不是 inline thread_local ；原因参见 @5.5.4.5 。
保持和 static inline 风格一致性，一般使用 explicit inline ，而不是 inline explicit 。

@5.5.6.2 语义：
注意 ISO C++ 规定一个 inline 函数总是应被声明为 inline ，这和 ISO C 不同。
注意 inline 的内联语义对实现只是建议而非强制。此外，不能忽视 inline 对于 ODR(@5.1.7) 的作用。
若能保证不降低源代码的可移植性，在必要时可以使用与编译环境相关的内联语法，但不直接使用非标准的内联关键字，而使用特定的宏定义代替。

@5.5.6.3
不连用 static inline ，以在未命名命名空间中的 inline 代替。

@5.5.6.4
在类的成员函数声明中可以省略 inline 关键字，参见 ISO C++03 7.1.2/3 。
若类的成员函数声明和定义分离，在完整定义而不是声明处使用 inline 。

@5.5.6.5 inline 函数名的链接：
注意 ISO C 和 ISO C++ 对于 inline 函数的链接的差异。 ISO C 的 inline 函数默认具有内部链接，而 ISO C++ 的内联函数默认具有外部链接。
按 ISO C++03 7.1.2 Function specifiers [dcl.fct.spec] 规定可知，非外部链接的内联函数内的局部静态对象不是同一对象。
按 ISO C++03 3.5 Program and linkage [basic.link] 规定可知，非外部链接的嵌套类名的成员函数不具有外部链接。
因此需要注意当使用内联成员函数且在其中定义静态对象时类名具有的链接。

@5.5.7 using ：
注意 using 声明优先于 using 指示。

@5.5.7.1 using 声明：
不使用冗余的 using 声明。
尽量避免在命名空间作用域内，尤其是头文件中使用 using 声明，以防名称污染。
在结构体/类中合理使用 using 声明使被隐藏成员可见，此时需要注意访问权限控制(@5.13.5) 。

@5.5.7.2 using 指令：
除非特别指定（例如文档说明），应避免在命名空间作用域内，尤其是头文件中使用 using 指令，以防名称污染。

@5.5.8 命名空间：
注意命名空间是实体，但具有链接。
注意命名空间具有作用域。
注意 ISO C++11 3.5/3 明确，命名空间具有的链接对其中声明的、名称未被指定为内部链接的特定实体（变量、函数、命名类、具有 typedef-name 的未命名类、命名枚举、具有 typedef-name 的未命名枚举、具有链接的枚举中的枚举项和模板）具有传递性。
注意全局命名空间。

@5.5.8.1 未命名命名空间(unnamed namespace) ：
注意可能 ISO C++03 中未命名命名空间具有外部链接，但可能被实现优化，如 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21581 。
注意 ISO C++11 3.5/4 明确，未命名命名空间及其中直接或间接的命名空间具有内部链接。
根据 @5.5.8 讨论的规则，未命名命名空间中的名称具有内部链接。

@5.5.8.2 命名空间别名：
尽量避免命名空间别名造成的名称歧义。

@5.5.8.3
在 ISO C++11 实现及启用某些扩展的实现（如 Clang++ ）中，可在命名空间定义(namespace-definition) 中使用 inline ，用于区分版本等。
和函数不同，对于命名空间声明，可以只在原始命名空间定义（ original-namespace-definition ，之前未存在其它定义）中使用，而不需要所有声明都指定 inline 。
只要能确定命名空间定义在翻译单元中是原始命名空间定义，其它同一命名空间的定义（ extension-namespace-definition ，扩展命名空间定义）中的 inline 冗余使用并非语言规则强制必要；但一般仍应使用 inline 清楚地表示 inline 命名空间。（已知 Clang++ 3.4 (trunk186265) 默认会对不使用 inline 的情况产生警告。）
注意 ISO C++ 要求若在定义中使用 inline ，则必须是原始命名空间定义。实现可能不严格检查（如 G++ 和 libstdc++ 的 bug ： http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53402 ）。

@5.5.9 友元：
禁止在类定义中定义友元类。
为保证代码清晰，一般不在类定义中定义友元函数。
除了以下提及的用法，避免使用友元。

@5.5.9.1 突破封装性的访问权限限制(@5.13.5) ：
友元无视访问权限控制的限制。

@5.5.9.2 名称查找：
友元被允许 ADL(@5.3.3.1) 查找。
参见 http://en.wikipedia.org/wiki/Barton%E2%80%93Nackman_trick 。

@5.5.10 修饰函数/函数模板的 constexpr ：
注意使用 constexpr 的语法和语义限制。
和 static 、 explicit 配合使用时类同 inline ，参见 @5.5.6.1 。

@5.5.11 属性(attributes) ：
按需使用属性。在实现支持时可以使用扩展，如 GCC 的 __attribute__ 和 Microsoft Visual C++ 的 __declspec ，并考虑用宏统一包装。
注意 ISO C++ 的属性被设计为尽量减少语义的改变，参见 http://herbsutter.com/2012/04/05/reader-qa-what-does-it-mean-for-attributes-to-affect-language-semantics/ 。

@5.5.11.1 [[noreturn]] ：
注意一个翻译单元中 [[noreturn]] 如在函数声明中出现，则每一个函数声明中都必须出现，否则程序形式非法但不要求诊断(@5.1.7) 。
注意若从 [[noreturn]] 返回则行为未定义。

@5.6 const 和 volatile 限定符(cv-qulifier) ：

@5.6.1 const ：
注意无 extern 时命名空间作用域声明的 const 对象名称具有内部链接，这点和 ISO C 不同。
若有可能，尽可能使用 const 关键字，除了以下给出的例外(@5.6.3) 。

@5.6.2
仅在有必要时使用 volatile 关键字。

@5.6.3 例外：
使用 constexpr 时不使用 const ，除保留修饰成员函数的 const 外。
可使用 constexpr 或 const 时尽量使用 constexpr 而不是 const ，除非有必要考虑兼容性。
在函数参数列表中，省略不直接修饰参数的 const 。
在异常捕获块和异常规范中，省略形式参数顶层的 const 和 volatile 修饰符。
函数参数类型在语义上有必要时，考虑不使用 const ，参见 @5.12.2 。

@5.7 类型关键字和模板：

@5.7.1
除非有必要，用非整数类型代替浮点数类型。

@5.7.2 整数类型：

@5.7.2.1 大小：
当需要时使用确定大小的整数类型。优先使用 <cstdint> 中支持的类型。

@5.7.2.2 符号和存储表示：
在位运算时尽量使用无符号整数。其它情况按需选取有符号数。
注意 ISO C/C++ 支持原码、反码或补码的有符号数表示的实现。多数实现使用补码。

@5.7.2.3 整数与指针类型：
注意指针类型和整数类型的大小不保证相等。
需要使用和对象指针占用空间大小相同的整数类型时，若实现支持（可选支持，参见 ISO C++11 18.4.1 ），使用 std::intptr_t 或 std::uintptr_t 。
除了 char 以外的内建字符类型关键字在位域外不需要被 signed 或 unsigned 修饰。

@5.7.2.4 字符类型：
 ISO C++98/03 支持 char 和 wchar_t 作为内建支持的字符类型。 ISO C++11 新增 char16_t 和 char32_t 类型，一般用于表示 Unicode 字符。
 ISO C/C++ 中， char 类型实际定义了字节的大小，即 sizeof(char) == 1 ，且具有 CHAR_BIT （注意 CHAR_BIT 不小于 8 ）二进制位。
注意 ISO C/C++ 中，和其它能被 signed 或 unsigned 修饰的整数类型不同 signed char 、 unsigned char 和 char 具有相同的大小和对齐要求，但是三种不同的类型。
注意 sizeof(wchar_t) 平台相关。而 char16_t 和 char32_t 分别表示至少能存储 16 位和 32 位二进制整数，并不表示确切的大小。

@5.7.3 枚举类型：
注意带作用域枚举(scoped enumeration) 在声明时不能省略作为枚举名称的标识符（参见 ISO C++11 7.2/2 ）。
 enum class 和 enum struct 语义等价（参见 ISO C++11 7.2/2 ），统一风格起见应尽可能使用 enum class 。

@5.7.4 class-key ：
关于带作用域枚举，参见 @5.7.3 。
根据基类和成员的可访问性(@5.13.5) 的需要适当选择 struct 或 class 。
对于同一个非 union 实体，在声明中总是一致地使用 struct 或 class 之一，以免某些非标准实现（如某些版本的 Microsoft C++ ）产生诊断消息。在某些实现启用诊断消息检查（如 Clang++ 使用 -Wmismatched-tags 警告）。

@5.7.5 this ：
注意 this 是实体（参见 ISO/IEC 14882 Clause 3 ）。
注意 this 的类型。
关于类模板中的使用，参见 @5.7.6 。

@5.7.6 模板声明中的关键字使用：
在定义模板类型（非模板）参数时 class 和 typename 等价，但应根据语义适当选择，以提升可读性：
若能确定模板类型参数仅适用于 class 类型（例如内部对此模板参数使用 std::is_class 等的静态断言），使用关键字 class ；否则使用关键字 typename 。
注意模板模板参数时的语法要求，适当使用 template class 。
不使用 export 。此特性在 ISO C++11 中被删除，但 export 关键字仍被保留。由于实现的限制，多数实现无法支持这一 ISO C++03 标准特性。
关于依赖名称，参见 @5.3.3.2 。

@5.7.7 模板名称：
注意除了成员函数模板外的模板名称具有外部链接。

@5.7.8 模板的实例化和特化：
注意特化的结果包含实例。
适当使用 ISO C++11 引入的显式实例化声明(extern template declaration) 以节约编译时开销。
注意模板的特化的链接。

@5.7.9 auto 和 decltype ：
 auto 使用模板推导规则。另见 @5.5.1 。
一般应尽量使用 auto （以及 auto& 或 auto&& ）合理缩减声明类型的复杂性，但当类型关键字能够被确定且不超过 4 个字符（即不长于 auto ）时直接使用类型名称而不是 auto 。
注意 decltype 结果与操作数是否为 id-expression 和是否带括号相关。
注意 C++1y 的 decltype(auto) 和 C++11 auto 的差异。

@5.8 操作符、内建操作和常量表达式(constant-expression) ：

@5.8.1
尽可能用对象名称代替类型名称作为 sizeof 的操作数，以在重编码时保持一致性。

@5.8.2 操作符重载：
参见 @5.12.3 。
注意内建操作和重载操作符在操作数要求值类别和求值顺序等限制不同。

@5.8.3 自增和自减：
注意前置自增/自减和赋值的等价性。
注意后置自增/自减的副作用。

@5.8.4 sizeof 、 alignof 和 alignas ：
注意 ISO C++ 的 sizeof 、 alignof 和 alignas 的表达式是静态求值的常量表达式(@5.8.11)，它们的操作数是非求值操作数(@5.2.6) 。
注意 ISO C99 引入的 VLA 的数组类型 sizeof 在运行时求值，但 ISO C++ 1y 引入的运行时确定的数组类型禁止使用 sizeof ，因此 sizeof 可确定是静态求值的常量表达式。

@5.8.5 new/delete 表达式：
注意 new 和 delete 匹配， new[] 和 delete[] 匹配，否则行为未定义。
注意 placement new 和（类类型的）析构函数匹配。
注意 new/new[] 失败时可能由 operator new 或构造函数抛出异常。
除非是对内置类型非静态数据成员的明确默认初始化（即不初始化）， new 必须初始化（即对于类类型也使用“ () ”而非省略）。

@5.8.6 显式类型转换：
参见 @5.11.4 。

@5.8.7 typeid ：
注意 typeid 的操作数是非求值操作数(@5.2.6) 。
注意 typeid 对非多态类参数静态求值，而对多态类参数在运行时确定动态类型，有一定运行时开销，且根据 ISO TR 18015 可能较 dynamic_cast 更难被实现优化。
另见 @5.11.4 。

@5.8.8 算术操作、逻辑操作和位操作：

@5.8.8.1 算术转换：
注意算术转换，特别是算术操作数被提升为 int 类型。

@5.8.8.2 溢出：
注意有符号数溢出是未定义行为。
四则运算、取余和向左移位均可能导致溢出。
除数为 -1 可导致溢出，如 http://kqueue.org/blog/2012/12/31/idiv-dos/ 。
注意 n 位无符号数的内建二元 + 、二元 - 、 * 、 ++ 、 -- 、 << 及对应复合赋值和一元 - 操作遵循模算术(modular arithmetic) ，保证不溢出而保证结果回绕为 2 ^ n 的余数。
应特别注意避免无符号数减法导致非预期的结果。参考： https://www.securecoding.cert.org/confluence/display/seccode/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap 。

@5.8.8.3 浮点数：
注意浮点数的舍入误差、非数值（如 NaN 和 Inf 等）和浮点环境。

@5.8.8.4 逻辑操作：
注意内建 && 和 || 的短路求值：在第一操作数满足条件时不对第二操作数求值。注意重载的 && 和 || 没有这个性质(@5.12.3) 。
另见 @5.4.1.1 。

@5.8.8.5 移位操作：
注意右移位时从高位填充 0 或 1 （实现为算术右移或逻辑右移）由实现定义。
另见 @5.8.3.2 。

@5.8.8.6 其它二元逻辑操作：
注意 & 、 | 和 ^ 的优先级。
注意 & 和 | 没有类似 && 和 || 的短路求值(@5.8.8.4) 。

@5.8.9 赋值表达式：
包括简单赋值表达式和复合赋值表达式，后者通过前者明确定义。
赋值操作的副作用在 ISO C11/ISO C++11 被更严格地限定顺序。
注意存在一些表达式在 ISO C90/99 和 ISO C++98/03 中存在未定义行为，但在 ISO C11 和 ISO C++11 正确的表达式如 i = ++i （另见 @5.8.3 ）。

@5.8.10 条件表达式：
注意条件表达式对值类别(@5.2.3) 的要求和影响。
注意 ISO C 和 ISO C++ 的条件表达式的语法差异。

@5.8.11 常量表达式：
特定的表达式可以在翻译时静态求值。
注意一些字面量、 const 修饰类型的特定表达式，以及 constexpr 决定的表达式是常量表达式。

@5.9 声明符和初始化：
注意区分涉及声明符的语法歧义，参见 ISO C++11 8.2 。

@5.9.1 声明符：
注意声明符的递归形式。
除非必要，避免使用复杂的声明符。

@5.9.2 直接初始化(direct initialization) 和复制(copy initialization) 初始化。
注意引起初始化特定的语法形式，区分直接初始化和复制初始化。
特定的上下文的初始化，如传递参数，总是复制初始化。
其它上下文中，用户声明变量或 new 语句中可以不同形式的语法指定不同的初始化。
复制初始化要求对象类型可被复制构造。注意对于非 trivally copyable 类型直接初始化和复制初始化的行为可能不同。在这些情况下不使用复制初始化。
其它语法使用规则参见 @5.9.2.2 。

@5.9.2.1 歧义：
注意“ () ”形式的直接初始化受限。
声明对象时的初始化列表必须非空且其参数不能是类型名的函数风格转换，否则会被解析为函数声明符的组成部分而不是初值符，参见 ISO C++ 8.2 。另见 @5.10 。

@5.9.2.2 语法使用：
按是否允许“ () ”形式的直接初始化规则分为两类。

@5.9.2.2.1 直接初始化优先：
除规则 @5.9.2.1 和 @5.9.3 更优先外，以下上下文中尽量使用“ () ”形式进行直接初始化。
适用于允许进行“ () ”形式的直接初始化的上下文，包括：
 compound-statement 和 for-init-statement 中声明变量时的 initializer ；
 new-expression 中的 new-initializer ；
 lambda-expression 内的 lambda-introducer 内 lambda-init 中的 initializer （ ISO C++14 起）。

@5.9.2.2.2 复制初始化优先：
对类类型以及不能排除是类类型的（如带有模板参数的）依赖类型的对象，尽量使用直接初始化以避免可能的复制开销；否则使用复制初始化。
注意在此 ISO C++11 也支持列表形式的直接初始化（“ {} ”）。
适用于“ = ”起始的复制初始化，但不支持“ () ”形式的直接初始化的上下文，包括：
 selection-statement 的 condition 内的初始化，包括 if 和 switch 语句的条件；
 iteration-statement 的 condition 内的初始化，包括 while 和 do-while 的条件以及 for 语句的可选条件；
 member-declarator 的可选 brace-or-equal-initializer ，即类定义内的成员初始化（ ISO C++11 起）。

@5.9.3 初值符、聚集(aggregates) 和初始化列表：
合理使用类似语法。
不引起含义改变时，使用 {} 代替较长的默认值，如 nullptr 或 false ，而不代替 0U 等。
不引起含义改变时，使用 {} 代替较长的初值符（ *-initializer ），如 nullptr 或 false ，而不代替 (0) 等。另见 @5.9.2.1 。

@5.10 语句和控制流：
编码时应注意避免干扰实现的分支预测优化。必要时可使用经过包装的特定实现的扩展。
语句中允许声明变量并初始化。初始化相关的语法使用规则参见 @5.9.2 。

@5.10.1 判断：
合理使用 if 语句代替 if-else 语句。

@5.10.2 无条件跳转：
尽可能不使用 goto ：仅在退出多层循环等少数具有明确语义且没有高效结构化控制流替代方式时使用。

@5.10.3 迭代和多分支：
合理减少 switch 块中的 break 的个数。
合理减少 break 和 continue 的个数。

@5.10.4 for 语句：

@5.10.4.1 for-init-statement 和 condition 子句：
注意 for-init-statement 必须存在，而 condition 是可选的。
使用的初始化语法规则不同，参见 @5.9.2.2 。

@5.10.4.2 expression 子句：
注意 expression 是可选的。
关于迭代条件的使用要点，参见 @5.8.3 和 @5.12.3.3 。

@5.10.4.3 range-based for ：
注意适当使用 begin 和 end 重载函数配合 range-based for 的使用。

@5.10.5 异常：
在必要时使用异常，而不是错误码或其它替代手段。
对于通用的接口，可以同时保留使用异常和错误码表示错误的版本。
用于表示正常流程结果不使用异常尽量使用返回值等其它手段。
在大的循环内部或立即需要处理错误时避免使用异常以保持代码清晰及减少不必要的性能开销。
除非有必要，不使用嵌套 try 块。

@5.10.5.1 异常安全：

@5.10.5.1.1 最低异常安全性保证：
总是保证最低安全性，避免异常处理造成资源泄露。

@5.10.5.1.2 强异常安全性保证：
必要时实现抛出异常后的状态回滚。

@5.10.5.1.3 无异常抛出保证：
必要时使用，禁止异常导致控制流中断。

@5.10.5.1.4 资源生存期：
优先使用 RAII 和确定性析构的 RRID(@2.3.2.3) 实现异常安全的设计。

@5.10.5.2 异常中立：
除非属于内部实现或异常能够被合适地完全处理，总是向调用者重新抛出捕获的异常。

@5.10.5.3 异常对象：
注意 throw 表达式中的对象需要满足可复制构造。
除非必要，抛出的异常对象应具有类类型，即异常类(@5.10.5.4) 。

@5.10.5.4 异常类：
避免抛出非类类型异常以便捕获抛出的异常对象。

@5.10.5.4.1 异常类特性：
异常类是空类或多态类。
除非必要（如考虑性能），一般以 std::exception 作为基类。
异常类可使用多重继承。
异常类可使用虚继承。

@5.10.5.4.2 异常类成员：
不包含 std::string 或其它有可能在复制构造时抛出异常的成员。这可能会直接导致程序异常终止。
不包含有可能在构造函数时抛出异常的成员，这可能会直接导致无法捕获预期类型的异常对象。
有必要时，格式化 what() 或其它成员的输出信息。

@5.10.5.5 异常规范：
除了本节指出的例外，在无异常抛出保证(@3.6.2.1.3) 的场合，应使用异常规范。
在非显式使用的异常规范上下文中，使用自定义的异常规范宏代替 throw 关键字。
注意动态异常规范是 ISO C++11 中的 deprecated 特性(@5.1.5) ，应限制使用（如仅用于调试）。
除异常类设计外，不显式地使用异常规范，而用异常规范宏代替。
注意 ISO C++11 规定的继承构造函数/模板和特殊成员函数的隐式异常规范。
注意覆盖虚函数的异常规范至少和被覆盖的虚函数一样严格。除非确定不覆盖（如作为 final 类或至少不使用 public 继承），析构函数一般不使用异常规范。

@5.10.5.5.1 noexcept 使用准则：
注意 ISO/IEC JTC1/SC22/WG21 N3248 明确了标准库使用 noexcept 的准则。
为了便于程序验证（可测试机性等），不直接在所有无异常抛出保证的函数上使用 noexcept ，仅当函数具有 wide contract ，即保证不（因为参数或状态违反前置条件）引起未定义行为时使用 noexcept 。
转移构造函数、转移赋值函数和 swap 需要使用 noexcept 。
析构函数不显式使用 noexcept 。注意 ISO C++ 标准库实践中析构函数不使用异常规范[ISO/IEC JTC1/SC22/WG21 N3508] 。
 ISO/IEC JTC1/SC22/WG21 N3263 在此基础上明确了标准库容器成员的 noexcept 使用。
一般库的设计应遵循标准库上述对异常规范的使用准则，但必要时经过文档另行约定，允许更严格的 noexcept 以明确接口要求。

@5.10.5.6 异常机制实现：
注意 C++ 和底层无 C++ 异常机制实现支持的回调代码的隔离。
注意不同实现的运行时之间不保证兼容。
注意特定平台异常机制和 C++ 异常在语言实现层次上的交互。应保证行为可预期。
有必要时避免使用 catch(...) 捕获所有异常，以免捕获非 C++ 异常。

@5.10.5.6.1 Windows 结构化异常：
注意扩展关键字和标准关键字的差异。
注意非 C++ 异常捕获的错误可以引起 Windows 结构化异常。

@5.10.6
除非必要，不使用 <csetjmp> 。

@5.11 标准转换、显式转换和类型使用限制：

@5.11.1 左值变换(lvalue transformation) ：
讨论重载(@5.12.1) 时，标准转换 lvalue-to-rvalue conversion 、 array-to-pointer conversion 和 function-to-pointer conversion 统称为左值变换。
注意函数参数和返回类型的退化(decaying) ：数组到指针，函数到函数指针。
可以使用 std::decay 显式实现。

@5.11.2
禁止使用变长数组，除非兼容性需要。

@5.11.3
使用 C++ 风格而不是 C 风格的类型转换。
足够清晰时使用 C++ 类构造函数语法代替 reinterpret_cast 和 static_cast 而不使用显式转换，以避免过于冗长。

@5.11.4 显式类型转换：
注意 dynamic_cast 依赖于运行时类型识别(RTTI) ，需要多态类(@5.13.3) 操作数；而其它三个关键字表示的转换在编译时确定，无此限制。
若有可能，使用 dynamic_cast 代替 typeid ；
若有可能，使用 static_cast 代替 dynamic_cast ；
若有可能，使用 static_cast 代替 reinterpret_cast 。
接口类型(@1.6.1) 转换可选 dynamic_cast ，但能保证类型安全且不被虚继承时首选 static_cast ，以提升性能。
如果可能（对于 simple-type-specfier 和 typename-specifier ），一般应使用函数调用形式代替 static_cast ，以保持简洁。
注意 const_cast 禁止用于转换 const 动态类型的对象，以免引起未定义行为。
注意在函数指针和对象指针之间的 reinterpret_cast 是有条件支持的(@5.1.4) 。

@5.11.5
除非显式约定布局，禁止对派生类的成员指针使用转换为基类成员指针的 static_cast ，以避免成员指针实现相关的错误。

@5.11.6 转换为 bool ：
注意 if 的条件表达式等上下文遵循 ISO C++11 的 contextually converted to bool ，此时无需转换。尽量使用此规则保证相关上下文中的无歧义和简洁。
注意 ISO C 的对应上下文中不使用此转换。
例如对于指针类型 p ，在 C++ 中使用 if(p) ，在 C 中使用 if(p == NULL) （而 if(p) 不保证等价）。
注意浮点数等允许通过标准布尔转换隐式转换为 bool 类型。
另见 @5.12.1 。

@5.12 函数/模板参数和重载：
注意函数重载和默认参数的使用的清晰性和易读性。

@5.12.1 函数重载：
避免不必要的重载和歧义。
重载使用复杂的规则。注意 explicit 关键字对重载的影响。
对于不期望隐式转换的类类型，使用 ISO C++11 引入的 explicit 转换操作符避免不必要的转换；在 ISO C++98/03 中使用转换为非公开成员指针类型代替。
注意函数和返回类型的限定符(@5.6) 和退化(@5.11.1) 不影响函数类型等价性。

@5.12.2 参数和返回：
除非以下讨论的语义上的必要性，不使用 const 左值引用类型以外的参数类型。另见 @5.12.1 。
参数类型和返回类型使用单一的 void ，但不能被限定符(@5.6) 修饰。
在需要完全的值类型语义且复制开销较小（例如传递一个内建整数类型的对象、内建指针、典型的迭代器、常见的函数对象）时，使用非引用类型形式参数或返回类型。
对于直接按值复制传递的函数参数，当需要按引用传递时，使用 std::ref 或 std::cref 包装。
（经验表明对于非空类类型的小对象， const 左值引用一般提供比直接使用对象更多的优化机会，例如包装整数类型的 union 在 G++ 4.7 上的表现。）
注意参数传递和返回值初始化是复制初始化，可能调用复制构造或转移构造函数，可能有复制省略，参见 @5.13.4.3 。

@5.12.2.1 参数类型：
注意只有没有参数的函数允许使用 void 参数类型，在 C++ 中一般省略。
注意非定义的函数声明中 C 和 C++ 对空参数列表的不同： C 的“ () ”相当于 C++ 的“ (...) ”，而 C 的“ (void) ”相当于 C++ 的“ () ”。
函数定义中 C 的“ () ”和 C++ 相同，但一般和原型声明保持一致以保持清晰。
在需要转移语义时，使用非 const 右值引用类型参数，同时使用 std::move 或等价的显式类型转换包装参数传递。

@5.12.2.2 返回类型和返回值：
除了 @5.12.2 的约定外，当返回对象可转移构造时，返回类型也可使用直接使用对象类型。
另见 @5.13.4.3 。

@5.12.2.3 参数传递：
仅向内部实现中的调用传递参数，外层参数使用非 const 右值引用类型时，同时使用 std::forward 或等价的显式类型转换包装参数传递。

@5.12.3 操作符重载：
对于一元操作符重载，使用成员重载。
对于参数形式对称的二元操作符重载，使用非成员重载并合理利用转换。
注意重载的操作符如 = 、 && 、 || 和 , ，没有和内建操作符相同的操作数值类别限制和求值顺序保证。

@5.12.3.1 限制特定的重载：
除非必要，不重载一元 operator& 和 一元 operator* 。若重载，需要和内建操作符的对应语义相关。
一般不重载 operator->* 和 operator, 。若重载，需要特别注意优先级。
二元操作符一般重载为非类成员，其它操作符一般使用重载为类成员。

@5.12.3.2 重载 operator= ：
注意 operator= 被派生类隐藏。
注意复制赋值函数和转移赋值函数是特殊成员，可以声明为 =default 。
转移赋值一般应保证无异常抛出(@5.10.5.1.3) 。
除非有特别说明，不应依赖转移赋值不引起实际参数状态的改变。
其它赋值无特殊限制。
经典复制赋值实现使用 copy-and-swap idiom 和 const 左值引用参数，能避免自赋值副作用且至少具有强异常安全性保证(@5.10.5.1.2) 。
由于异常规范仅适用于块，不涉及参数复制的异常，因此当函数体内保证无异常抛出时，可以直接使用无异常抛出保证的异常规范。
通过使用非引用参数代替 const 左值引用的 operator=(unifying assignment operator) ，可以获得对象复制的优化，但具有以下缺点：
重载右值引用参数的 operator= 会引起重载歧义，即无法通过单独重载优化的转移赋值（对于转移赋值，使用 copy-and-swap 需要多一步复制/转移构造）；
无条件复制，无法根据被复制的对象的状态进行优化；
若没有 trivial 复制赋值，没有转移赋值会导致以此类对象作为成员的类无法使用默认生成转移赋值（隐式地，或声明为 = default ，都相当于 = delete ）。
因此，除非被复制的对象具有完全的（所有子对象均满足）值语义，一般不重载非引用参数的 operator= ，而分别重载 const 左值引用参数和非 const 右值引用参数的版本（也可能不需要转移赋值，仅重载前者）。
若转移赋值是必要的，一般应确保存在可访问的转移构造函数。
对于保存存储状态的不完全值语义对象（例如容器），使用最小赋值：在 operator= 的实现中判断状态，以避免分配不必要的存储空间。
对于其它不完全值语义对象，若转移赋值是必要的，使用以下实现：
具有明确的 clear 操作回复值的状态时，使用判断自赋值的 clear-and-swap 实现，可以期望比 copy-and-swap 具有更好的性能（因为通常不需要大量 clear 操作）；
当不需要 clear 操作回复状态（例如约定调用方保证参数是临时对象）时，可直接 swap ；
其它情况使用默认简单实现，即对每个子对象进行转移赋值（可以显式使用 = default ）。

@5.12.3.3 重载自增和自减：
在相同作用域内，前置和后置自增/减被同时定义时，尽量保证它们的语义一致性，并通过前置自增/减来实现后置版本。若有必要改变，必须给出注释说明。
能使用前置自增/减实现相同效果时，不用后置自增/减。

@5.12.3.4 重载 operator() ：
允许多个重载 operator() 。应特别注意成员 operator() 的 cv-qualifier 。
当存在多个重载候选时，通过 std::enable_if 或其它 SFNIAE 进行选择。若无法选择，调用其它成员（模板）。

@5.12.3.5 重载转换操作符：
允许重载操作符模板。应特别注意成员 operator() 的 cv-qualifier 。
当存在多个重载候选时，通过非模板优先于模板匹配进行有限选择。若无法选择，调用其它成员。

@5.12.3.6 重载operator new 、 operator new[] 、operator delete 和 opertor delete[] ：
不依赖重载成员 operator new 、 operator new[] 、operator delete 和 opertor delete[] 声明的隐式 static ，显式使用 static 关键字以明示不隐含 this 。

@5.12.4 默认参数：
合理地使用函数默认参数。需要注意参数顺序。

@5.12.4.1
在虚函数中应避免使用默认参数。
若需要使用默认参数，应在基类中使用具有默认参数的非虚成员函数调用没有默认参数的非 public 虚函数。

@5.13 类：
类是类型。
类类型包含 class 和 union 。

@5.13.1 类名：
类名声明不是定义。
类名声明引入的类是不完整类型。

@5.13.2 类的成员：
静态成员函数同非成员函数，除了受到访问权限控制(@5.13.5)  的作用。
非静态成员函数操作受限。

@5.13.2.1 成员初始化：
注意成员初始化顺序。
除非是对内置类型非静态数据成员的明确默认初始化（即不初始化），每个成员必须初始化（另见 @5.8.5 ）。
注意 ISO C++ 支持成员直接在类定义内初始化。可使用列表初始化或复制初始化，使用的语法和策略同 if 条件中的使用，参见 @5.10.1 。
除了类定义内的初始化外，在构造函数内初始化非静态成员。除非必要，尽量使用直接初始化而不是列表初始化或以赋值代替初始化。

@5.13.3 派生类：
注意空基类优化：基类子对象可能占用零存储。
继承和访问权限控制(@5.13.5) 相关。注意 C++ 中，类的成员是否被继承不受权限控制的影响。
具有虚函数或虚基类的类是多态类。虚基类无法静态转换为派生类。适当平衡运行时开销。
虚基类的初始化顺序和非虚基类不同。

@5.13.4 特殊成员函数：
注意排除模板。
区分隐式声明和定义。
注意 ISO C++ 构造函数和析构函数中调用虚函数行为同非虚函数，这和 Java 、 C# 、 C++/CLI 和早期的非标准 C++ 的类似特性不同。

@5.13.4.1 默认构造函数：
注意默认构造函数可能有默认参数。

@5.13.4.2 隐式声明：
注意隐式声明的特殊成员函数具有的异常规范。

@5.13.4.3 复制和转移：
注意 ISO C++ 11 12.8/31 指定的允许复制省略(copy elision) 的特殊规则。
注意 ISO C++ 11 12.8/32 指出对于允许省略复制时对重载解析的影响：
注意 ISO C++11 关于隐式声明复制构造函数和复制赋值操作符的 deprecated 特性。
对于 return 或 throw 作用的以名称出现的非 volatile 类类型自动对象（除函数和 catch 的参数外），不需要 std::move 即可优先转移，仅当无法转移时复制。
关于复制赋值/转移赋值，参见 @5.12.3.2 。

@5.13.5 访问权限控制：
访问权限控制决定可访问性。
注意访问权限控制和可见性相互独立。
注意对于一般实现，访问权限控制仅在编译时检查。
关于友元，参见 @5.5.9 。

@5.13.5.1 默认访问权限：
注意 class 默认具有 private 、 struct 默认具有 public 。
访问权限控制对大多数成员声明能体现实际语义，因此不依赖于省略默认访问权限，除了以下例外：
省略成员访问权限：友元声明和 static_assert 声明，对此无论何种访问权限都不显式改变语义，因此这些声明应出现在类定义中的第一个 access-specifier 前；
省略基类访问权限：明确的基类继承，如 struct 元函数(@3.10) 继承或混入操作符模板类继承。

@5.13.5.2 访问权限选择策略：
本节的语义包括领域逻辑语义和语言限定的其它语义。
对于语义要求公开的接口，使用 public 。
对于语义要求非公开的接口，尽量使用 private ，其次使用 protected ，若存在实现限制则使用友元。
注意数据成员同时体现直接读写访问的接口。若需要不同层次的读写访问权限，应该使用 private 保护数据成员，同时使用访问器(accessor) ，即 getter 和/或 setter 满足不同的需要。
对于其它成员，若没有明确限制接口非公开，在能保证访问清晰明确时首先使用 protected 代替 private ，以避免实现可能不必要的间接适配（调用）层次的负担。最小接口(@3.1.3) 在之后的重构时体现。
对于体现 LSP（Liskov Substitution Principle ，里氏替换原则）的空开接口继承，使用 public 。
对于实现混入(mixin) 但需要由派生类定制的基类继承，使用 protected 。
对于其它体现实现的继承，使用 private 。

@5.13.5.3 非静态数据成员访问权限：
注意显式指定非静态数据成员的访问权限可能影响布局和分配顺序。
 ISO C++03 9.2/12 规定不同 asscess-specifier 声明的非静态数据成员所在的地址相对顺序和之间的分配顺序是未指定的，这包括相同的访问权限。
 ISO C++11 放宽了语言规则的限制但限制了实现： ISO C++11 9.2/13 规定不同访问权限的非静态数据成员所在的地址相对顺序和之间的分配顺序是未指定的。
此外， ISO C++11 9/7 规定含有不同访问权限的非静态数据成员的类不是标准布局类，因此也不是标准布局类型(@5.2.2)。

@5.13.6 虚函数：

@5.13.6.1 覆盖(overriding)：
虚函数可以使用显式的 qualified-id 进行调用以取消动态多态，否则虚函数调用最终覆盖版本(final overrider) 。
注意避免函数签名的修饰符差异导致遗漏覆盖。
注意虚函数的覆盖不影响访问权限。

@5.13.6.2 纯虚函数：
纯虚函数是特殊的虚函数。
没有非虚覆盖版本的纯虚函数导致所在的类是抽象的，无法构造对象。具有虚析构函数，非静态成员函数都是纯虚函数的抽象类，可作为接口类型(@2.4.1) 使用。
注意 C++ 的纯虚函数的定义可选，一般用于提供默认实现。

@5.13.6.3 NVI（Non-Virtual Interface ，非虚接口）模式：
虚函数不一定需要作为公开接口。此时，用 private 或 protected 保护虚函数不被外部访问。
具体选择 private 或 protected 虚函数取决于是否确定需要显式 qualified-id 调用(@5.13.6.1) 影响。其它选择策略参见 @5.13.5.2 。
以调用虚函数的基类的成员函数提供访问时，实现模板方法(template method) 模式。
以友元调用虚函数时，实现虚友元(virtual friend) 模式。

@5.14 I/O 操作：
注意 I/O 操作是副作用。
其它参见 @5.15.12 。

@5.15 标准库：

@5.15.1 名称使用限制：
本节“实现”指 C++ 核心语言和标准库实现。
除非另有说明，本节中引用的标号分别表示 ISO C++03 和 ISO C++11 同时对应且内容一致的章节（若标号相同则只使用一个）。

@5.15.1.1 命名空间使用：

@5.15.1.1.1 namespace std ：
按 ISO C++03 17.4.3.1 Reserved names [lib.reserved.names] 和 ISO C++11 17.6.4.2.1 Namespace std [namespace.std] 规定，对全局命名空间 std 的使用受限，仅允许在满足其它条款要求时添加模板的特化。

@5.15.1.1.2 namespace posix ：
按 ISO C++11 17.6.4.2.2 Namespace posix [namespace.posix] 规定，全局命名空间 posix 及其中的名称保留给实现使用。

@5.15.1.2 保留名称：

@5.15.1.2.1
按 17.4.3.1.1/17.6.4.3.1 Marco Names [lib.extern.names] 规定，可能使用标准库头文件的用户程序翻译单元不得使用词法上等价于关键字的名称作为宏名。

@5.15.1.2.2
按 17.4.3.1.2/17.6.4.3.2 Global Names [lib.global.names] 规定，以下名称保留给（核心语言和标准库）实现使用：
包含连续双下划线 "__" 或以下划线 "_" 紧接大写字母起始的名称；
在全局命名空间和 ::std 命名空间内以下划线 "_" 起始的名称。

@5.15.1.2.3
按 17.4.3.1.3/17.6.4.3.3 External linkage [lib.extern.names] 规定，以下名称保留给（核心语言和标准库）实现使用：
在头文件中，在 std 命名空间或在全局命名空间的具有外部链接的对象名称，例如 <cerrno> 中定义的 errno ；
在头文件中，具有外部链接的全局函数签名；
外部链接的全局命名空间的对象和函数以及 std 命名空间的对象；
具有 extern "C" 或 extern "C++" 链接的包含连续双下划线 "__" 的名称；
 C 标准库(Standard C library) 使用的具有 extern "C" 链接，在 std 命名空间或在全局命名空间的名称；
 C 标准库(Standard C library) 声明的具有 extern "C" 或 extern "C++" 链接，在全局命名空间的函数签名。

@5.15.1.2.4
按 17.4.3.1.4/17.6.4.3.4 Types [lib.extern.types] 规定，对于 C 标准库的每一个类型名称 T ， ::T 和 std::T 保留给实现使用。

@5.15.1.2.5
禁止使用 override 、 final 、 carries_dependency 和 noreturn 作为宏名，参见 ISO C++11 C.2.7 Clause 17: library introduction [diff.cpp03.library] 。

@5.15.2 ISO C++11 直接指定的依赖项：
本节“包含”的含义参见 ISO C++11 17.6.5.2/1 ，即被指示为包含的头文件中的标准库接口的声明和定义保证和包含此头文件等效。

@5.15.2.1 由 Synopsis 节显式指定：
 <algorithm> 、 <array> 、 <deque> 、 <forward_list> 、 <list> 、 <map> 、 <queue> 、 <set> 、 <stack> 、 <random> 、 <regex> 、 <string> 、 <unordered_map> 、 <unordered_set> 、 <valarray> 、 <vector> 、 <utility> 包含 <initializer_list> ；
 <ios> 包含 <iosfwd> ；
 <bitset> 包含 <string> 和 <iosfwd> ；
 <isotream>包含 <ios>、<streambuf>、<istream>、<ostream>。

@5.15.2.2 补充指定：
 ISO C++11 24.6.5/1 指定，除 <iterator> 外，以下头文件被包含时 24.6.5 的函数模板（即 std::begin 和 std::end ）也可用：
 <array> 、 <deque> 、 <forward_list> 、 <list> 、 <map> 、 <regex> 、 <set> 、 <string> 、 <unordered_map> 、 <unordered_set> 和 <vector> 。

@5.15.3 C 标准库：
不使用 ISO C 标准库头文件名，以 ISO C++ 对应无扩展名的头文件代替。注意命名空间。

@5.15.3.1 内存管理：
如无必要，不使用 realloc 。
注意 ISO C 标准库关于内存分配的设计遵循无隐式 malloc 规则(no-implicit-malloc rule) ，而 POSIX 和其它实现忽略（参见 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1106.txt )。

@5.15.4 可替换实现的接口：
全局函数 operator new 、 operator new[] 、 operator delete 和 operator delete[] 可替换定义。
注意这些函数不能以 inline 修饰，实现可不给出违反此规则的诊断(@5.1.7) 。
注意 ISO C++11 起基本的抛出异常形式的全局 operator new 和全局 operator delete 提供了其它可替换函数的基本功能实现。如替换其中的函数，其它函数的行为也可被影响。
注意 ISO C++11 起允许全局 operator new 抛出 std::bad_alloc 以外的异常。

@5.15.5 处理器函数(handler fucntion) ：
处理器函数是 std 命名空间中以 set_* 和 get_* 为名的函数，提供基本一些例程，和整个标准库的状态相关。
调用这些函数不引起数据竞争。

@5.15.6 共享对象和线程安全性：
注意在不同线程间使用可引入数据竞争的标准库函数的程序行为未定义。
标准库定义的类类型的对象的构造函数调用完成应发生在任何成员函数调用之前。

@5.15.7 类型特征(type traits) ：
类型特征于 ISO C++ TR1 和 ISO C++11 中引入，属于元编程设施。
合理使用类型特征进行关系判断，如 is_same 判断类型相同。
合理使用类型特征进行类型操作，如 std::add_lvalue_reference 可避免泛型代码中出现非法的 void& 。

@5.15.8 智能指针(smart pointer) ：
智能指针于 ISO C++ TR1 和 ISO C++11 中引入，用于管理资源。
由于转移语义， C++11 能引入 std::unique_ptr 取代 C++98/03 的 std::auto_ptr ，避免后者区分转移困难、无法作为容器元素等局限。
仅当需要共享资源时使用 shared_ptr ，否则尽量使用 unique_ptr 。

@5.15.8.1 元素类型：
注意 std::unique_ptr 的析构要求元素是完整的对象类型，而 std::shared_ptr 允许直接使用不完整类型（包括 void ）。

@5.15.8.2 make_* ：
使用 std::make_shared 减少分离的内存分配（注意涉及动态删除器可能使二进制文件体积增大）
使用 std::make_shared 和 ISO C++14 引入的 std::make_unique 而不是直接使用可能抛出异常的 new 保证异常安全。若没有 std::make_unique ，自行实现。参见 http://herbsutter.com/gotw/_102/ 。
因此，仅当涉及分配单一副作用的顺序确定时才能直接使用来修改智能指针对象（包括但不限于作为赋值的操作数以及 reset 成员函数的参数）。

@5.15.9 容器：
注意容器对元素的要求。
注意异常安全。保证无异常抛出的成员函数不一定显式使用 noexcept ，参见 @5.10.5.5.1 。
若有可能，使用 empty 代替 size 。
若有可能，使用 emplace 代替 insert 。

@5.15.10 迭代器：
注意迭代器类别(iterator category) 。
注意 std::iterator 的继承应该为 public 继承，否则需要显式在派生类中声明类型名以免失效。对于迭代器类模板，依赖名称(@5.3.3.2) 若作为 std::iterator 的参数，总是需要重新声明。

@5.15.11 算法：
注意部分的算法复杂度和类型满足的要求相关。

@5.15.12 C++ 标准 I/O
可以同时使用 C++ 标准流和 printf/scanf 函数族进行格式化输入/输出处理，但在考虑效率（以及目标文件大小）时应尽量避免使用 C++ 标准流。
应注意 nifty counter idiom(http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter) 对多翻译单元程序大小的影响。
正确使用 printf/scanf 函数族格式化输入输出的控制字符。

@6 类 C 语言编码风格导引：
仅叙述之前章节未涉及的内容。
源代码外观仅考虑使用等宽字体的水平显示。

@6.1 字符和编码：
禁止使用的字符参见 @5.3.1 。
源代码文件的默认编码使用 UTF-8 ，其它情况需要说明，否则视为临时文件。

@6.2 预处理记号：

@6.2.1 解析：
不使用双联符(digraph) 和三联符(trigraph) 。
必要（当实现不支持 C++11 预处理器特性）时使用一个空格表示预处理记号的边界，避免构成双联符或三联符，如 <:: 改为 < :: 。
注意 ISO C++11 当后续字符不为 > 或 : 时对 <:: 解析为 < 和 :: 而不是 <: 和 : ， ISO C++03 没有此规则。

@6.2.2
不使用替代表达的保留字，参见 @5.4.1 。

@6.2.3
不在一元操作符的表达式内部使用多余的空白符；其它含有（预处理记号的）标点的表达式应保证周围有且仅有一个空白符。

@6.2.4 括号：
除了典型的防止被认为错误（如 if 条件中的赋值表达式或不同层次连续嵌套的 if 和 else 子句）避免警告，不使用不改变语义的冗余的小括号或大括号。
注意小括号可避免使用 ADL (@5.3.3.1) 。
 alignas 、 alignof 和 sizeof 表达式使用最外层有括号的形式。
注意 decltype 表达式的子表达式的括号的语义。
 return 语句使用无最外层括号形式。

@6.2.5 填充空白符：
作为后缀表达式的组成部分或控制语句紧接关键字后的组成部分的 ( 和左边的标识符（包括关键字，如 catch 、 if 、 for 和 while ）之间不插入额外的空白符。
不使用针对标点的后缀空白符。

@6.3 行首空白符：
不依赖水平制表符的显示宽度，除非另外说明其非缩进的特殊用途。
默认水平制表符显式为 4 个半角字符（以等宽字体的空格计，下同）。
区分缩进和对齐。缩进使用水平制表符，对齐使用空格。
避免对齐样式依赖于制表符和空格的宽度比。
一般不单独使用对齐。
同一层次的缩进统一使用制表符或相同宽度的空格。
在以上规则约束下，以下缩进使用尽可能少的制表符。
其它行内空白符使用参见 @6.6 。一般执行策略参见 @6.8.2 。

@6.3.1 段落缩进：
块使用缩进。
命名空间的直接成员不使用缩进。
标签不使用缩进。
初始化列表的 : 前使用缩进。
其它非预处理代码（如语句、函数或模板形式参数列表、类或类模板定义的成员列表）若需要换行，第二行起使用相同的缩进。

@6.3.2 换行后缩进：
非复合语句换行后使用缩进。
紧接在续行符后的下一个文本行使用缩进，除非断行在字符串字面量内部。

@6.4 分行：
本节约定具体规则。一般执行策略参见 @6.8.2 。

@6.4.1 行宽和断行连接：
默认行宽 80 个半角字符。
标识符的使用应注意（考虑缩进和对齐后）不超过此限制。其它情况下可以使用行尾的续行符 \ 进行断行连接。
除了标识符超过行宽导致必须分行的情形，当续行符之前存在预处理记号时，两者之间至少一个或多个（仅当需对齐时）空格。
必要时可以同时使用字符串字面量和断行连接。

@6.4.2 语句分行：
任意不同语句（包括复合语句和块的第一个子语句）应起始于不同行。

@6.4.2.1 例外 1 ：
声明/初始化相同类型的对象。

@6.4.2.2 例外 2 ：
执行顺序无关的多条短语句序列。
另参见 @6.4.3.3 。

@6.4.3 列表分行：
本节约定列表语法（ISO C++ 中 -seq 或 -list 结尾的语法元素），包括语句、函数或模板形式参数列表、类或类模板定义的成员列表、初始化列表等的分行规则，需要满足以上规则及 @6.6 。
为了描述方便，本节视列表组成元素结尾可选或之后紧接的分隔符（如 , ）包含于列表项。
除了较长的列表项或以下另有说明外，优先使用紧缩分行(@6.4.3.2) 。

@6.4.3.1 宽松分行：
每一个列表项需要独立占一行。
非宽松分行的不同列表项可以占据同一行。可能会造成可读性降低，酌情使用。

@6.4.3.2 紧缩分行：
紧缩分行是以尽量少占用总代码行数的目标的分行策略，是非宽松分行的特殊情况。
枚举、类和类模板的成员声明一般不使用紧缩分行，以避免造成成员注释过于紧凑。
除非一个记号无法在单行内按指定缩进容纳，不使用续行符。否则，若列表项无法被容纳时，在该项之前换行，且保证行尾不是空白符(@6.6) 。

@6.4.3.3 半紧缩分行：
非宽松分行也非紧缩分行的分行方式。可以视为若干组紧缩分行（每一组至少一行）。
一般初始化列表中的基类子对象初始化和成员对象初始化分为两组半紧缩分行。

@6.4.4 语句序列(statement-seq) 转写：
多个连续的语句若没有相对顺序的严格关系，可以写成以 , 分隔的列表。
在 operator, 可能被重载的上下文中除外，以免混淆。
若表达式具有非 void 类型，可以使用函数参数列表和宏进行辅助。此时求值顺序真正地未被限定，可以有利于优化。
对于使用内建 operator, 的情况，则除了语法上的不同语句可以合并为同一语句这一变化外，仅作为对代码阅读者的提示。

@6.4.5 括号：
括号 { 、 } 、 [ 、] 、 ( 、 ) 标识声明符以上层次的语法（包括领域专门内嵌语言(domain-specific embedded language)）结构（如函数体）时应独立占一行，除了以下例外：
构成空序列时连写（如 {} 表示空函数体）独立占一行；
 lambda 表达式中起始的 { 前不换行。
除此之外，列表分行以括号右边优先于括号左边，即左括号在分行后作为末尾的记号。如函数参数列表或后缀调用表达式太长时，可在 ( 之后而不是之前分行；模板参数列表太长时，可在 < 之后而不是之前分行。
另见 @6.8.1 。

@6.4.6 模板声明：
模板声明中 template 和被声明的模板名称及模板修饰符以外的修饰符不在同一行，该行以 > 结束。
注意 ISO C++11 对模板上下文 >> 解析为独立的两个 > 而不是操作符 >> ， ISO C++03 没有此规则。一般不在连续的 > 之间分行。

@6.4.7
除非仅作为显式转换使用的类型名临时使用，不使用无法从左到右直接解析的复杂函数声明符，保证函数声明符能拆分成返回类型和非返回类型（包含参数列表）两部分。
函数及函数模板声明中的返回类型和函数修饰符独占一行。

@6.4.8 一般分行：
列表项和其它语法成分（如表达式）混合分行时，列表内容按语法树层次优先：先以上层成分为单位尝试分行，若失败（超过行宽限制(@6.4.1) ）则最后一个成分递减，递归进行，直至记号超长需要续行。
除明确指定的分行规则外，以记号为单位贪婪分行：即尽量使用较少的行；符合其它规则时使最后行保持最短。

@6.5 空行：
本节约定具体规则。一般执行策略参见 @6.8.2 。

@6.5.1
不使用超过 2 行的空行。

@6.5.2 源代码文件：
在 @5.3.1 的基础上，在源代码文件尾留空行；默认为 2 行。
若文件起始内容为授权声明和版本说明等注释内容(@6.7.4) ，建议和之后的其它内容之间空 2 行。

@6.5.3
 #include 指令和非预处理指令之间应该保留空行。

@6.5.4
除同名（包括重载以及构造函数/构造模板/析构函数之间同属无名实体的情形）函数/函数模板定义外，类类型定义、枚举类型定义和函数/函数模板定义之间应该保留空行。

@6.5.5 块作用域：
块的内部应该避免空行，除非用于标识声明语句。
除临时用途（如测试）外，块内不使用函数声明，因此空行可有效分隔和标识 using /类型/变量声明和其它代码。
有必要时多个声明可以被拆分为若干不连续的部分，之间允许存在其它代码。
如无特殊需要，连续的声明的顺序依次为 using 声明、类型声明和变量声明。
因逻辑原因标识分隔语句块的，应考虑改用（未命名命名空间的、 inline 的）函数 、 lambda 表达式或其它实体形式包装，而不是插入空行进行分隔。另见 @6.8.1 。

@6.6 分词：
除 @6.3 和 @6.4 外，仅使用空格分隔记号。
注释和字面量外的代码中，除了缩进和对齐(@6.3) 需要外，只使用单独的空格表示间隔。
除 @6.6.2 ，一个记号的所有字符应保证在同一行内。
除非使用多声明符的声明符列表，同一行内的声明符或抽象声明符的 * 和 & 都向左和语法元素靠拢，和右边的语法元素保持一个空格。
除字面量内部，空白符不出现于行尾。

@6.6.1 标点：
行的两端除了之前用于缩进的水平制表符和用于对齐的空格外没有多余的空白符。回避双联符或三连符时允许增加必要的一个空格。
除了以下关于 : 的例外，除去行首的可能存在的空白符后，标点 , 、: 和 ; 不出现于行首（除非此行紧接在预处理指令后），其它操作符不出现于行尾。
除以上规则适用时，一元操作符及 . 和 -> 的标点和操作数记号之间无空白符；其它括号外的操作符的标点和操作数记号之间有空白符。
关于 ( ，另见 @6.2.4 。关于括号，另见 @6.4.5 。

@6.6.1.1 例外：
 : 表示基类列表或初值符列表时，除去行首可能存在的空白符后置于行首，以保持语法和语义的一致性（ : 与增加或修改的列表项在逻辑上是连贯的），也便于插入预处理指令。

@6.6.2 例外：
当超过行宽时允许操作符的标点不在同一行内，此时使用续行符保证逻辑上的行的连续性。

@6.7 注释：

@6.7.1
适用单行注释时不使用多行注释。注意断行连接。

@6.7.2
适用多行注释时可以使用单行注释代替，但行数较大时应首选多行注释。
不在单行注释内部使用多余的 / 修饰外观。
不在多行注释内部使用多余的 * 修饰外观。

@6.7.3
使用注释文档化工具管理时应注意格式统一。

@6.7.4
在非临时的源代码文件头部加入授权声明和版本说明等。

@6.8 综合编码风格：
默认使用 Allman style 。注意 ISO C 使用 K&R 为主，而 ISO C++ 混合多种风格。
例外：
函数返回类型使用类 BSD KNF/GNU 风格，即第一个非指针声明符（ noptr-declarator ，参见 ISO/IEC 14882 Clause 8 ）后换行。

@6.8.1 复合语句：
在块内部除非必要（析构函数的副作用），不使用冗余的复合语句的边界表示层次。
对于只含一个语句的复合语句，除非语法限制（如作为函数体）和以下例外，转换为非复合语句。

@6.8.1.1 例外：
为便于搜索区分， do-while 的循环体边界保留 { 和 } 。
（注意按 @6.2.5 ， } 和 while 之间不保留空白符。）

@6.8.2 一般缩进、分行和空行策略：
对于每个预处理翻译单元按以下顺序执行代码格式化算法。
按 @6.5.2 组织文件起始和末尾的空行；
按 @6.5.3 组织预处理之间的空行；
排除已约定的影响的固定策略的上下文（如标识语句位置或组织语句块的宏），若占据若干单独的行即排除整行；
按 @6.8.2.1 处理。

@6.8.2.1 翻译单元缩进、分行和空行策略：
对于翻译单元内的顶级声明按行首空白符规则(@6.3) 处理；
按 @6.5.4 组织顶级声明之间的空行；
按 @6.8.2.2 处理。

@6.8.2.2 块作用域缩进、分行和空行策略：
按 @6.5.5 在声明、非声明以及断言等可能涉及预处理语法构造之间划分必要的空行；
对上述划分的每个部分按 @6.8.2.3 处理。

@6.8.2.3 语句缩进、分行和空行策略：
若为复合语句，按 @6.8.2.2 递归处理；
按 @6.8.2.4 处理。

@6.8.2.4 非复合语句缩进、分行和空行策略：
试验符合 @6.3 、 @6.4.1 、 @6.4.2 和 @6.6 的规则约束下最紧凑（尽可能少地使用空白符）的代码格式，记录代码行数；
在满足以上规则和结果行数的约束下增加 @6.4 的其余约束，若存在解则算法结束；
否则结果行数增加 1 ，继续验证上述增加 @6.4 的其余约束的解是否存在。
显然不限制结果行数上限时解一定存在。算法结束。

@6.9 类成员和类定义内声明规则：
以下为一般建议性规则。若满足 ISO/IEC C++ 或 ISO/IEC C++ TR 内指出的接口要求或参照类似接口，经指出后不使用此顺序。
除非另有说明，关于声明顺序排列的规则的优先级以从高到低排列。

@6.9.1 基本原则：
一致性原则：声明和实现（定义）若分离，顺序应保持一致，以便查找。
类定义内声明顺序规则：分为区段规则和非区段规则，参见 @6.9.2 。
当且仅当公开实现时，在类定义内提供公开函数体的成员函数定义，但成员函数模版因为复杂性可以例外。
仅在必要时使用类名声明。

@6.9.2 声明区段(section) ：
为明确顺序，划分类定义内的声明的组合为若干区段。
同一区段的声明之间连续（即不穿插其它区段的声明），不同区段之间具有明确的顺序。
区段按声明的语法形式归类划分。区段内可以划分子区段（如按限定符）。
根据区段明确的声明顺序规则称为区段顺序规则。非区段顺序规则优先于区段顺序规则。

@6.9.3 非区段顺序规则：
若应用区段顺序规则后导致使用未声明的名称，且可以通过调整声明顺序解决，则允许调整声明顺序。
非别名声明的 using 声明和 static_assert 声明不受区段顺序规则限制。
除了数据成员布局需要，无视访问权限。

@6.9.4 区段顺序一般规则：
同一区段内，非静态成员先于静态成员。

@6.9.5 声明区段划分和特定区段顺序规则：
总体区段以类型/模板类型、数据成员、其它成员或非成员（包括类定义内的友元声明等）顺序排列。

@6.9.5.1 类型/模板类型声明：
一般应该保证非模板优先。

@6.9.5.2 数据成员：
分为两个区段，以静态数据成员、非静态数据成员的顺序排列。

@6.9.5.2.1 静态数据成员
按 cv-qualifier 和 constepxr 分为以下区段，以 constexpr 、 const 、 const volatile 、 无限定 、 volatile的顺序排列。

@6.9.5.3 其它成员或非成员：

@6.9.5.3.1 名称区段：
操作符（以 operator 起始）名称在同一区段其它名称之前；
其它成员或非成员声明按各区段之间的名称在用于满足特定的接口约定（如 ISO C++ 容器要求）时按接口约定排列，否则按字典序排列。

@6.9.5.3.2 非成员区段与成员区段：
名称相同的非成员函数与非成员函数模板先于对应类型的成员函数与成员函数模板。

@6.9.5.3.3 重载区段：
构成重载的所有成员声明之间不插入其它成员声明。
对于同一个名称的成员，成员重载先于非成员重载。
涉及特殊成员函数的重载以默认构造函数、其它构造函数/构造模板、复制构造函数、转移构造函数、析构函数、其它赋值操作符函数/模板、复制赋值操作符函数、转移复制操作符函数的顺序声明，优先于以下子区段规则。
仅限定符不同或仅修饰相同位置参数中的限定符构成重载的区段：首先按 cv-qualifier 以无限定、const 、volatile 、const volatile 排列，其次按 ref-qualifier 以无限定、 & 、 && 排列；但命名空间作用域中若在接口语义或实现中存在声明（调用）依赖则允许使用其它顺序（但应尽少改变）。
类型和所有的限定符一致的成员函数先于成员函数模板。

@6.9.5.3.4 伪重载区段：
以 const_ 前缀修饰类型名同 @6.9.5.3.3 规则排列，如 iterator 先于 const_iterator 。

@6.9.6 一般具体声明顺序：
以下同一区段内，按约定顺序排列；约定同类顺序的， @6.9.5.3.1 的规则排列。
当需要向前引用名称查找依赖声明顺序的成员（如 using 别名需要静态 constexpr 对象的值）时可以存在尽可能少的例外。
友元类和友元模板；
嵌套类、嵌套类模板；
 typedef 或代替 typedef 的 using 别名；
 using 声明；
静态 constexpr 数据成员；
静态非 constexpr 的 const 数据成员；
静态无限定数据成员；
静态 volatile 数据成员；
非静态数据成员；
默认构造函数；
以基类引用参数作为唯一参数的构造函数；
以基类引用参数作为唯一参数的构造模板；
其它（排除首个参数与以下提及同类的相同的，下同）构造函数或构造模板；
复制构造函数；
（对于类模板）和复制构造函数仅有首个函数参数类型的模板参数不同的构造模板；
转移构造函数；
（对于类模板）和转移构造函数仅有首个函数参数类型的模板参数不同的构造模板；
接受初值符列表的构造函数；
析构函数；
用于逻辑初始化的 private 静态或非静态成员函数或成员模板；
用于逻辑初始化的 protected 静态或非静态成员函数或成员模板；
替换为包括超过一个函数或函数模板的成员声明的宏调用；
以基类引用参数作为唯一参数的赋值操作符函数；
以基类引用参数作为唯一参数的赋值操作符模板；
其它赋值操作符函数或模板；
复制赋值操作符；
转移赋值操作符；
接受初值符列表的赋值操作符；
组合赋值操作符（以 += 、 -= 、 *= 、 /= 、 %= 、 <<= 、 >>= 、 &= 、 |= 的顺序）；
一元操作符（以 ! 、 ~ 、 + 、 - 、 & 、 * 的顺序)；
重载 operator-> ；
重载 operator->* ；
自增/自减（以前缀自增、后缀自增、前缀自减、后缀自减的顺序）；
重载 operator[] ；
关系操作符（以 == 、 != 、 < 、 <= 、 > 、 >= 的顺序）；
算术操作符（以 + 、 - 、 * 、 / 、 % ）的顺序；
二元位操作符（以 << 、 >> 、 & 、 | 、 ^ 的顺序）；
逻辑操作符（以 && 、 || ）的顺序；
分配/去配操作符（以 new 、new[] 、 delete 、 delete[] 的顺序）；
转换操作符（以整数类型、枚举类型、其它基本类型、类类型顺序；整数类型之间以转换阶(conversion rank) 从小到大的顺序排列）；
其它函数或函数模板。

@6.10 宏嵌入式领域特定语言(macro embedded domain-specific language) ：
使用 C/C++ 宏实现的领域特定语言若可约定与内建语言类似形式（函数调用等）不同的语义，则可约定以上规则的例外。
宏调用可能被替换为表达式，称为表达式宏。
非表达式宏结束一般不冗余语句结尾的标点（ ; 或 } ）。

*/
////

