std::memory_order

std::memory_order

定义在头文件 <atomic>

typedef enum memory_order {
	memory_order_releaxed,
	memory_order_consume,
	memory_order_acquire,						// (since C++11)
	memory_order_release,						// (until C++20)
	memory_order_acq_rel,
	memory_order_seq_cst
} memory_order;
enum class memory_order : /*unspecified*/ {
	relaxed, consum, acquire, release, acq_rel, seq_cst
}
inline constexpr memory_order memory_order_relaxed = memory_order::relaxed;
inline constexpr memory_order memory_order_consume = memory_order::consume;
inline constexpr memory_order memory_order_acquire = memory_order::acquire;
inline constexpr memory_order memory_order_release = memory_order::release;		// (since C++20)
inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel;
inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst;

std::memory_order 指定原子操作周围的内存访问如何进行排序,包括常规的,非原子的内存访问。当多线程同时访问几个变量时,在多核系统上缺乏任何约束,一条线程观察值的变换的顺序可能不同于另一线程的写值顺序。实际上,值改变的顺序甚至在多个读取线程中都不尽相同。一些类似的现象可能出现在单处理器系统上,因为内存模型允许编译器进行转换(读写内存顺序)。

库中提供的所有原子操作的默认行为都使用 sequentially consistent ordering(见下述讨论)。默认值可能会影响性能,但是库的原子操作能够提供一个额外的 std::memory_order 参数来指定原子性之外的具体约束,编译器和处理器必须以指定 std::memory_order 约束强制执行该操作。

Constants

定义于头文件 <atomic> 中。

memory_order_relaxed

relaxed operation:对其他读写行为无同步或顺序约束,仅保证本操作的原子性。

Relaxed ordering

标记为 memory_order_relaxed 的 Atomic 操作并非同步操作;对并行的内存访问并不强加顺序。仅保证原子性和修改顺序的一致性。例如,x 和 y 初始化为 0。

// Thread 1
r1 = y.load(std::memory_order_relaxed); // A
x.store(r1, std::memory_order_relaxed); // B
// Thread 2
r2 = x.load(std::memory_order_relaxed); // C
y.store(42, std::memory_order_relaxed); // D

上述代码允许产生 r1 == r2 == 42,因为,虽然线程 1 中的A在B之前,线程 2 中 C 在 D 之前,在对 y 的修改的顺序中,无法避免 D 在 A 之前发生,在对 x 的修改的顺序中,无法避免 B 在 C 之前发生。D在y上的边际效应对线程1中的 load A 可见,与此同时,B在x上的边际效应对线程2中的 load C 亦可见。特别是,如果线程 2 中的 D 在 C 之前完成,这或是由于编译器的重新排序亦或时运行期间的重新排序使 D 在 C 之前完成,这种情况就有可能会发生。

线程中的 D 在 C 之前完成,对于使用 Relaxed Ordering 内存模型的原子操作,编译器可能会做一些优化,对于原子操作的执行顺序不做保证,虽然在代码形式上是顺序执行的,但是编译/运行期间的机器指令并不一定保证顺序进行。

即使使用 relaxed 内存模型,out-of-thin-air 的值也不允许循环地依赖它们自己的计算,例如,x 和 y 初始化为 0:

// Thread 1
r1 = y.load(std::memory_order_relaxed);
if(r1 == 42) x.store(r1, std::memory_order_relaxed);
																	// (since C++ 14)
// Thread 2
r2 = x.load(std::memory_order_relaxed);
if(r2 == 42) y.store(42, std::memory_order_relaxed);

上述代码不允许产生 r1 == r2 == 42 因为仅当 42 被存储到 x 中时,42 才有可能被存储到 y 中,它又循环的依赖 42 被存储到 y 中。注意直到 C++14,规范在技术上允许这样做,但不建议这样的实现。

Relaxed 内存模型的典型使用是逐步增加的计数器,例如 std::shared_ptr 的引用计数器,因为它仅需要原子性,不需要顺序性和同步性 (注意 shared_ptr 计数器的减少需要 acquire-release synchronization 在析构函数中)

Code
#include <vector>
#include <iostream>
#include <thread>
#include <atomic>
 
std::atomic<int> cnt = {0};
 
void f()
{
    for (int n = 0; n < 1000; ++n) {
        cnt.fetch_add(1, std::memory_order_relaxed);
    }
}
 
int main()
{
    std::vector<std::thread> v;
    for (int n = 0; n < 10; ++n) {
        v.emplace_back(f);
    }
    for (auto& t : v) {
        t.join();
    }
    std::cout << "Final counter value is " << cnt << '\n';
}

Output;

Final counter value is 10000
memory_order_consume

使用此 memory order 的 load 操作,在受影响的 memory location 上执行 consume operation:当前线程中, 没有依赖当前加载的值的读或写操作能在此 load 执行之前被重新排序。在其他线程中(release 相同的 atomic variables),写 data-dependent 的值对当前线程来说是可见的。在大部分平台,该行为仅影响编译器优化(见下述 Release-Consume ordering)

Release-Consume ordering

如果线程 A 中的一个原子 store 被标记为 memory_order_release,且线程 B 中,一个对相同变量放入原子 load 被标记为 memory_order_consume,从线程 A 的角度,所有发生在原子 store 之前的内存写(非原子的和 relaxed 原子的)成为了线程 B 中这些操作可见的边际效应,线程 B 中 load 操作携带依赖,即,一旦原子 load 完成,线程 B 中的这些操作和函数使用从 load 中获取的值,被保证能看到线程 A 中的写内存的内容。
仅仅在 releasing 和 consuming 相同的原子变量的线程中建立同步。其他线程可能会看到与同步线程中的其一或全部线程不同的内存访问顺序。
这种顺序的典型使用案例涉及对很少写的同步数据结构的读访问(路由表,配置,安全协议,防火墙规则等),和使用指针作为中介发布的 publisher-subscribler 场景,即,当 producer 发布一个指针,通过这个指针 consumer 能够访问信息:不需要让所有 producer 写入内存的数据对 consumer 可见(在 weakly-ordered 架构上,这个操作可能是昂贵的)。这样场景的一个例子是 rcu_dereference。

Code
#include <thread>
#include <atomic>
#include <cassert>
#include <string>
 
std::atomic<std::string*> ptr;
int data;
 
void producer()
{
    std::string* p  = new std::string("Hello");
    data = 42;
    ptr.store(p, std::memory_order_release);
}
 
void consumer()
{
    std::string* p2;
    while (!(p2 = ptr.load(std::memory_order_consume)))
        ;
    assert(*p2 == "Hello"); // never fires: *p2 carries dependency from ptr
    assert(data == 42); // may or may not fire: data does not carry dependency from ptr
}
 
int main()
{
    std::thread t1(producer);
    std::thread t2(consumer);
    t1.join(); t2.join();
}
memory_order_acquire

使用此 memory order 的 load 操作,在受影响的 memory location 上执行 acquire operation:在本次 load 之前,当前线程中任何读写操作都不能被重新排序。release 相同 atomic variable 的其他线程中的所有写操作,对当前线程都是可见的(见下述 Release-Acquire ordering)。

Release-Acquire ordering

如果线程 A 中的 atomic store 被标记为 memory_order_release,且线程 B 中对相同变量的一个 atomic load 被标记为 memory_order_acquire,从线程 A 的角度来看,所有发生在 atomic store 之前的内存写,在线程 B 中变成 visible side-effects,即,一旦 atomic load 被完成,保证线程 A 写内存的所有内容对线程 B 可见。This promise only holds if B actually returns the value that A stored, or a value from later in the release sequence.

同步仅在多线程 releasing 和 acquiring 相同的 atomic 变量时建立。其他线程可能会看到与同步线程中的其一或全部线程不同的内存访问顺序。

在 strongly-ordered 系统上 – x86,etc-- release-acquire ordering 自动应用于大部分操作。对于这种同步模式,不会发出发出额外的 CPU 指令;只有特定的编译器优化被影响(e.g. 编译器禁止移动 non-atomic stores 到 atomic store-release 之后或在 atomic load-acquire 之前执行 non-atomic loads)。在 weakly-ordered 系统(ARM,etc),特定的 CPU load 或 memory fence 指令被使用。

互斥锁(Mutual exclusion locks),例如 std::mutex 或 atomic spinlock,是 release-acquire 同步的一个例子:当 lock 被线程 A 释放,且被线程 B 获取,发生在线程 A 上下文临界部分(在释放之前)的所有事情必须对线程 B 可见(在获取之后),线程 B 也正在执行相同的临界部分。

Code
#include <thread>
#include <atomic>
#include <cassert>
#include <string>
 
std::atomic<std::string*> ptr;
int data;
 
void producer()
{
    std::string* p  = new std::string("Hello");
    data = 42;
    ptr.store(p, std::memory_order_release);
}
 
void consumer()
{
    std::string* p2;
    while (!(p2 = ptr.load(std::memory_order_acquire)))
        ;
    assert(*p2 == "Hello"); // never fires
    assert(data == 42); // never fires
}
 
int main()
{
    std::thread t1(producer);
    std::thread t2(consumer);
    t1.join(); t2.join();
}

下述的例子示范了三个线程中过度的 release-acquire ordering。

#include <thread>
#include <atomic>
#include <cassert>
#include <vector>
 
std::vector<int> data;
std::atomic<int> flag = {0};
 
void thread_1()
{
    data.push_back(42);
    flag.store(1, std::memory_order_release);
}
 
void thread_2()
{
    int expected=1;
    while (!flag.compare_exchange_strong(expected, 2, std::memory_order_acq_rel)) {
        expected = 1;
    }
}
 
void thread_3()
{
    while (flag.load(std::memory_order_acquire) < 2)
        ;
    assert(data.at(0) == 42); // will never fire
}
 
int main()
{
    std::thread a(thread_1);
    std::thread b(thread_2);
    std::thread c(thread_3);
    a.join(); b.join(); c.join();
}
memory_order_release

使用此 memory order 的 store 操作执行 release operation:当前线程中任何读写操作都不能在此次 store 之后重新排序。当前线程中的所有写操作对其他线程都可见,只要线程获得相同的 atomic variable(见下述 Release-Acquire ordering),且携带依赖的对原子量的写操作对其他线程可见,只要线程 consume 相同的 atomic(见下述 Release-Consume ordering)

memory_order_acq_rel

使用此 memory order 的 read-modify-write 操作既是一个 acquire operation 也是一个release operation。当前线程的任何读写在此次 store 之前和之后都不能被重新排序。release 相同原子量的其他线程中的所有写在修改(当前线程的 store)之前都是可见的,且修改(当前线程的 store)对 acquire 相同原子量的其他线程都是可见的。

memory_order_seq_cst

使用此 memory order 的 load 操作执行一个 acquire operation,store 执行 release operation,且 read-modify-write 即执行acquire operation 又执行 release operation,加上存在一个总顺序,在所有线程观察到所有操作以这个相同的顺序排序。(见下述 Sequentially-consistent ordering)

Sequentially-consistent ordering

标记为 memory_order_seq_cst 的原子操作,不仅仅是使用与 release/acquire 排序相同的方式进行内存排序(同一线程所有在 store 之前发生的操作,都对其他线程的 load 可见),也为所有这样标记的原子操作建立了一个 single total modification order

Formal description

线程间同步和内存排序决定 evaluations(求值)和表达式的 side effects 如何在不同执行线程间排序。他们在下述术语中被定义:

Sequenced-before

相同的线程中,evaluation A 可能排在 evaluation B 之前,如 evaluation order 所述。

Carries dependency

相同的线程中,排序在 evaluation B 之前的 evaluation A 可能也携带一个依赖到 B 中(即,B 依赖于 A),如果下述任何项成立:

  1. A 的值被用做 B 的操作数,除了
    a) B 是对 std::kill_dependency 的调用
    b) A 是内置 &&,||,?:,or,operators 的左操作数。
    2)A 写入 scalar 对象 M,B 从 M 中读取
    3)A 携带依赖到另一 evaluation X 中,且 X 携带依赖到 B 中。
Modification order

对特定原子量的所有修改依据向这个原子量指定的总顺序发生。

任何对原子量的修改依序发生

所有的原子操作都保证有下述四种需求:

1)Write-write coherence: 如果 evaluation A 修改 atomic M(a write),它在 evaluation B 之前发生,B 也修改 M,那么在 M 的修改顺序中 A 排在 B 之前

(对原子量的修改) A 发生在B之前,A 的执行顺序排在 B 之前。
A(W)–>B(W)

2)Read-read coherence: 如果对 atomic M 的值计算 A(a read)发生在对 M 的值计算 B 之前,且如果值 A 来自对 M 的写 X,那么 B 的值也是由 X 存储的值,或者是由 M 上的 side-effect Y 存储的值,在 M 的修改顺序中,它排在 X 之后。

X(W)–>A(\R)–>Y(W)–>B(\R)

对原子量的读顺序与发生顺序保持一致。

3)Read-write coherence: 如果 atomic M 的值计算 A 发生在 M 的 B 操作(a write)之前,那么 A 的值来自 在 M 的 modification order中 发生在 B 之前的 side-effect(a write)X。

X(W)–>A(\R)–>B(W)

4)Write-read coherence: 如果对 atomic object M 的 side effect(a write)X 发生在 M 上的操作 B(a read)之前,那么 evaluation B 将会从 X 或 在 M 的修改顺序中排在 X 之后的某一 side effect 操作 Y 中获得其值。

X(W)–>Y(W)–>B(\R)

Release sequence

release operation A 在一个 atomic object M 上执行之后, M 的修改顺序的最长连续子序列由以下项组成:
1)由执行 A 的相同线程执行的写 (until C++ 20)
2)任何线程对 M 的 atomic read-modify-write 操作作为 release sequence headed by A 被熟知

Dependency-ordered before

在线程中,evaluation A is dependency-ordered before evaluation B,如果下述项为真:
1)A 在某 atomic M 上执行 release operation ,且,在不同线程中,B 执行对相同的 atomic M 执行 consume operation,且 B 读取由 以 A 为首的 release sequence 任意部分所写的值。
2)A is dependency-ordered before X 且 X 携带 dependency 进入 B。

Inter-thread happens-before

在线程中,evaluation A inter-thread happens before evaluation B, 如果任何下述项为真:

  1. A synchronizes-with B
  2. A is dependency-ordered before B
  3. A synchronizes-with some evaluation X,and X is sequenced-before B
  4. A is sequenced-before some evaluation X, and X inter-thread happens before B
  5. A inter-thread happens-before some evaluation X, and X inter-thread happends-before B
Happens-before

抛开线程,evaluation A hanppens-before evaluation B,如果下述为真:
1)A is sequence-before B
2)A inter-thread happens before B

实现需要保证hanppen-before 关系是非循环的,通过引入额外的同步是必要的(只有在涉及消费操作才是必要的)

如果某 evaluation 修改 memory location,且其他 evaluation 读或者修改相同的 memory loaction,且如果至少一个 evaluation 不是原子操作,项目的行为是未定义的(程序有 data race)除非在两个 evaluation 中存在 happens-before 关系。

Visible side-effects

scalar M 上的 side-effect A 对 M 上的 value computation B(a read)是 visible,如果下述项全为真时:
1)A happens-before B
2)没有其他的 side effect X 使得 A happens-before X 且 X happens-before B

如果 side-effect A 对 value computation B 可见,那么对 M 的 side-effects 的最长持续子集,在修改顺序中,B 没有在 happen-before 它,被称为visible sequence of side-effects。(M 的值,由 B 决定,将成为这些 side effects 所 store 的值的其中之一)

Note:线程间同步可以归结为避免 data races(通过建立 happens before 关系)和定义在某种情况下何种 side effects 可见。

Consume operation

使用 memory_order_consume or stronger 的 atomic load 是 consume operation。注意 std::atomic_thread_fence 强加比 consume operation 更强的同步操作。

Acquire operation

使用 memory_order_acquire or stronger 的 atomic load 是 acquire operation。Mutex 的 lock() operation 也是一个 acquire operation。注意 std::atomic_thread_fence 强加比 acquire operation 更强的同步要求。

Release operation

使用 memory_order_release or stronger 的 atomic store 是 release operation。Mutex 的 unlock() 操作也是 release operation。注意 std::atomic_thread_fence 强加比 release operation 更强的同步要求。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
内容简介回到顶部↑这本书不适合C++ 初学者,不适合 Genericity(泛型技术)初学者,或 STL 初学者。这本书也不适合带领你学习面向对象(Object Oriented)技术 — 是的,STL 与面向对象没有太多关连。本书前言清楚说明了书籍的定位和合适的读者,以及各类基础读物。如果你的Generic Programming/STL实力足以阅读本书所呈现的源码,那么,恭喜,你踏上了基度山岛,这儿有一座大宝库等着你。源码之前了无秘密,你将看到vector的实现、list的实现、heap的实现、deque的实现、RB-tree的实现、hash-table的实现、set/map 的实现;你将看到各种算法(排序、搜寻、排列组合、数据移动与复制…)的实现;你甚至将看到底层的memory pool 和高阶抽象的traits 机制的实现。那些数据结构、那些算法、那些重要观念、那些编程实务中最重要最根本的珍宝,那些蜇伏已久彷佛已经还给老师的记忆,将重新在你的脑中闪闪发光。 目录回到顶部↑庖丁解牛(侯捷自序) i 目录 v 前言 xvii 本书定位 xvii 合适的读者 xviii 最佳阅读方式 xviii 我所选择的剖析对象 xix 各章主题 xx 编译工具 xx 中英术语的运用风格 xxi 英文术语采用原则 xxii 版面字形风格 xxiii 源码形式与下载 xxiv 在线服务 xxvi 推荐读物 xxvi 第1章 STL 概论与版本简介001 1.1 STL 概论 001 1.1.1 STL的历史 003 1.1.2 STL与C++ 标准程序库 003 . 1.2 STL 六大组件 - 功能与运用 004 1.3 GNU源码开放精神 007 1.4 HP STL实现版本 009 1.5 P.J. Plauger STL实现版本 010 1.6 Rouge Wave STL实现版本 011 1.7 STLport 实现版本 012 1.8 SGI STL实现版本 总览 013 1.8.1 GNU C++ header 文件分布 014 1.8.2 SGI STL 文件分布与简介 016 STL 标准头文件(无扩展名) 017 C++ 标准规格定案前,HP规范的STL头文件(扩展名 .h) 017 SGI STL 内部文件(SGI STL真正实现于此) 018 1.8.3 SGI STL 的组态设定(configuration) 019 1.9可能令你困惑的C++ 语法 026 1.9.1 stl_config.h 中的各种组态 027 组态3:static template member 027 组态5:class template partial specialization 028 组态6:function template partial order 028 组态7:explicit function template arguments 029 组态8:member templates 029 组态10:default template argument depend on previous template parameters 030 组态11:non-type template parameters 031 组态:bound friend template function 032 组态:class template explicit specialization 034 1.9.2 临时对象的产生与运用 036 1.9.3 静态常数整数成员在class 内部直接初始化 037 in-class static const integral data member initialization 1.9.4 increment/decrement/dereference 运算子 037 1.9.5 "前闭后开"区间表示法 [ ) 039 1.9.6 function call运算子(operator()) 040 第2章 空间配置器(allocator) 043 2.1 空间配置器的标准接口 043 2.1.1 设计一个简单的空间配置器,JJ::allocator 044 2.2 具备次配置力(sub-allocation)的SGI 空间配置器 047 2.2.1 SGI 标准的空间配置器,std::allocator 047 2.2.2 SGI 特殊的空间配置器,std::alloc 049 2.2.3 构造和析构基本工具:construct() 和 destroy() 051 2.2.4 空间的配置与释
该资源不适合C、C++初学者,可作为C++高手向大师级进化的参考书。 内容: ... 17 Library introduction 17.1 General 17.2 The C standard library 17.3 Definitions 17.4 Additional definitions 17.5 Method of description (Informative) 17.6 Library-wide requirements 18 Language support library 18.1 General 18.2 Types 18.3 Implementation properties 18.4 Integer types 18.5 Start and termination 18.6 Dynamic memory management CONTENTS v c ISO/IEC N3000=09-0190 18.7 Type identification 18.8 Exception handling 18.9 Initializer lists 18.10Other runtime support 19 Diagnostics library 456 19.1 General 19.2 Exception classes 19.3 Assertions 19.4 Error numbers 19.5 System error support 20 General utilities library 20.1 General 20.2 Requirements 20.3 Utility components 20.4 Compile-time rational arithmetic 20.5 Tuples 20.6 Metaprogramming and type traits 20.7 Function objects . 520 20.8 Memory 541 20.9 Time utilities 583 20.10Date and time functions 596 20.11Class type_index 596 21 Strings library 599 21.1 General 599 21.2 Character traits 599 21.3 String classes 605 21.4 Class template basic_string 608 21.5 Numeric Conversions 635 21.6 Null-terminated sequence utilities . 636 22 Localization library 640 22.1 General 640 22.2 Header <locale> synopsis 640 22.3 Locales 641 22.4 Standard locale categories . 653 22.5 Standard code conversion facets 693 22.6 C Library Locales 695 23 Containers library 696 23.1 General 696 23.2 Container requirements 696 23.3 Sequence containers 719 23.4 Associative containers . 758 23.5 Unordered associative containers . 776 24 Iterators library 791 24.1 General 791 24.2 Iterator requirements 791 CONTENTS vi c ISO/IEC N3000=09-0190 24.3 Header <iterator> synopsis 796 24.4 Iterator primitives 799 24.5 Iterator adaptors . 802 24.6 Stream iterators . 816 25 Algorithms library 825 25.1 General 825 25.2 Non-modifying sequence operations 835 25.3 Mutating sequence operations 839 25.4 Sorting and related operations 848 25.5 C library algorithms 862 26 Numerics library 864 26.1 General 864 26.2 Numeric type requirements . 864 26.3 The floating-point environment 865 26.4 Complex numbers 866 26.5 Random number generation . 876 26.6 Numeric arrays 920 26.7 Generalized numeric operations 940 26.8 C Library 944 27 Input/output library 949 27.1 General 949 27.2 Iostreams requirements . 950 27.3 Forward declarations 950 27.4 Standard iostream objects 952 27.5 Iostreams base classes . 954 27.6 Stream buffers 972 27.7 Formatting and manipulators 982 27.8 String-based streams 1009 27.9 File-based streams 1021 28 Regular expressions library 1036 28.1 General 1036 28.2 Definitions 1036 28.3 Requirements 1037 28.4 Header <regex> synopsis 1039 28.5 Namespace std::regex_constants 1045 28.6 Class regex_error 1048 28.7 Class template regex_traits 1048 28.8 Class template basic_regex 1051 28.9 Class template sub_match 1056 28.10Class template match_results 1062 28.11Regular expression algorithms 1066 28.12Regular expression Iterators . 1070 28.13Modified ECMAScript regular expression grammar 1076 29 Atomic operations library 1079 29.1 General 1079 29.2 Header <atomic> synopsis 1079 CONTENTS vii c ISO/IEC N3000=09-0190 29.3 Order and Consistency . 1082 29.4 Lock-free Property 1084 29.5 Atomic Types 1085 29.6 Operations on Atomic Types 1094 29.7 Flag Type and Operations 1098 29.8 Fences . 1099 30 Thread support library 1101 30.1 General 1101 30.2 Requirements 1101 30.3 Threads 1102 30.4 Mutual exclusion . 1107 30.5 Condition variables 1121 30.6 Futures 1129 A Grammar summary 1149 A.1 Keywords 1149 A.2 Lexical conventions 1149 A.3 Basic concepts 1154 A.4 Expressions . 1154 A.5 Statements . 1158 A.6 Declarations . 1159 A.7 Declarators . 1162 A.8 Classes . 1164 A.9 Derived classes 1165 A.10 Special member functions 1165 A.11 Overloading . 1165 A.12 Templates 1166 A.13 Exception handling 1167 A.14 Preprocessing directives 1167 B Implementation quantities 1169 C Compatibility 1171 C.1 C++ and ISO C 1171 C.2 Standard C library 1181 D Compatibility features 1185 D.1 Increment operator with bool operand . 1185 D.2 static keyword . 1185 D.3 Access declarations 1185 D.4 Implicit conversion from const strings . 1185 D.5 register keyword 1185 D.6 C standard library headers . 1185 D.7 Old iostreams members 1186 D.8 char* streams 1187 D.9 Binders 1196 D.10 auto_ptr 1198 E Cross references 1201 Index 1218 CONTENTS viii ISO/IEC N3000=09-0190 Index of Grammar Productions 1243 Index of Library Names 1246 Index of Implementation Defined Behavior 1280
庖丁解牛(侯捷自序) i 目录 v 前言 xvii 本书定位 xvii 合适的读者 xviii 最佳阅读方式 xviii 我所选择的剖析对象 xix 各章主题 xx 编译工具 xx 中英术语的运用风格 xxi 英文术语采用原则 xxii 版面字形风格 xxiii 源码形式与下载 xxiv 在线服务 xxvi 推荐读物 xxvi 第1章 stl 概论与版本简介001 1.1 stl 概论 001 1.1.1 stl的历史 003 1.1.2 stl与c++ 标准程序库 003 . 1.2 stl 六大组件 - 功能与运用 004 1.3 gnu源码开放精神 007 1.4 hp stl实现版本 009 1.5 p.j. plauger stl实现版本 010 1.6 rouge wave stl实现版本 011 1.7 stlport 实现版本 012 1.8 sgi stl实现版本 总览 013 1.8.1 gnu c++ header 文件分布 014 1.8.2 sgi stl 文件分布与简介 016 stl 标准头文件(无扩展名) 017 c++ 标准规格定案前,hp规范的stl头文件(扩展名 .h) 017 sgi stl 内部文件(sgi stl真正实现于此) 018 1.8.3 sgi stl 的组态设定(configuration) 019 1.9可能令你困惑的c++ 语法 026 1.9.1 stl_config.h 中的各种组态 027 组态3:static template member 027 组态5:class template partial specialization 028 组态6:function template partial order 028 组态7:explicit function template arguments 029 组态8:member templates 029 组态10:default template argument depend on previous template parameters 030 组态11:non-type template parameters 031 组态:bound friend template function 032 组态:class template explicit specialization 034 1.9.2 临时对象的产生与运用 036 1.9.3 静态常数整数成员在class 内部直接初始化 037 in-class static const integral data member initialization 1.9.4 increment/decrement/dereference 运算子 037 1.9.5 "前闭后开"区间表示法 [ ) 039 1.9.6 function call运算子(operator()) 040 第2章 空间配置器(allocator) 043 2.1 空间配置器的标准接口 043 2.1.1 设计一个简单的空间配置器,jj::allocator 044 2.2 具备次配置力(sub-allocation)的sgi 空间配置器 047 2.2.1 sgi 标准的空间配置器,std::allocator 047 2.2.2 sgi 特殊的空间配置器,std::alloc 049 2.2.3 构造和析构基本工具:construct() 和 destroy() 051 2.2.4 空间的配置与释放,std::alloc 053 2.2.5 第一级配置器 __malloc_alloc_template 剖析 056 2.2.6 第二级配置器 __default_alloc_template剖析 059 2.2.7 空间配置函数allocate() 062 2.2.8 空间释放函数deallocate() 064 2.2.9 重新充填free-lists 065 2.2.10 内存池(memory pool) 066 2.3 内存基本处理工具 070 2.3.1 uninitialized_copy 070 2.3.2 uninitialized_fill 071 2.3.3 uninitialized_fill_n 071 第3章 迭代器(iterators)概念与 traits 编程技法 079 3.1 迭代器设计思维 - stl关键所在 079 3.2 迭代器是一种 smart pointer 080 3.3 迭代器相应型别(associated types) 084 3.4 traits 编程技法 - stl源码门钥 085 partial specialzation(偏特化)的意义 086 3.4.1 迭代器相应型别之一value_type 090 3.4.2 迭代器相应型别之二difference_type 090 3.4.3 迭代器相应型别之三pointer_type 091 3.4.4 迭代器相应型别之四reference_type 091 3.4.5 迭代器相应型别之五iterator_category 092 以advanced() 为例 093 消除 "单纯传递调用函数" 097 以distance() 为例 098 3.5 std::iterator class 的保证 099 3.6 iterator相关源码完整重列 101 3.7 sgi stl的私房菜:__type_traits 103 第4章 序列式容器(sequence containers) 113 4.1 容器概观与分类 113 4.1.1 序列式容器(sequence containers) 114 4.2 vector 115 4.2.1 vector 概述 115 4.2.2 vector 定义摘要 115 4.2.3 vector 的迭代器 117 4.2.4 vector 的数据结构 118 4.2.5 vector 的构造与内存管理:constructor, push_back 119 4.2.6 vector 的元素操作:pop_back, erase, clear, insert 123 4.3 list 128 4.3.1 list 概述 128 4.3.2 list 的节点(node) 129 4.3.3 list 的迭代器 129 4.3.4 list 的数据结构 131 4.3.5 list 的构造与内存管理:constructor, push_back, insert 132 4.3.6 list 的元素操作:push_front, push_back, erase, pop_front, 136 pop_back, clear, remove, unique, splice, merge, reverse, sort 4.4 deque 143 4.4.1 deque 概述 143 4.4.2 deque 的中控器 144 4.4.3 deque 的迭代器 146 4.4.4 deque 的数据结构 150 4.4.5 deque 的构造与内存管理 :ctor, push_back, push_front 152 4.4.6 deque 的元素操作:pop_back, pop_front, clear, erase, insert 161 4.5 stack 167 4.5.1 stack 概述 167 4.5.2 stack 定义式完整列表 167 4.5.3 stack 没有迭代器 168 4.5.4 以list 做为stack 的底层容器 168 4.6 queue 169 4.6.1 queue 概述 169 4.6.2 queue 定义式完整列表 170 4.6.3 queue 没有迭代器 171 4.6.4 以list 做为queue 的底层容器 171 4.7 heap(隐式表述,implicit representation) 172 4.7.1 heap 概述 172 4.7.2 heap 算法 174 push_heap 174 pop_heap 176 sort_heap 178 make_heap 180 4.7.3 heap 没有迭代器 181 4.7.4 heap 测试实例 181 4.8 priority-queue 183 4.8.1 priority-queue 概述 183 4.8.2 priority-queue 定义式完整列表 183 4.8.3 priority-queue 没有迭代器 185 4.8.4 priority-queue 测试实例 185 4.9 slist 186 4.9.1 slist 概述 186 4.9.2 slist 的节点 186 4.9.3 slist 的迭代器 188 4.9.4 slist 的数据结构 190 4.9.5 slist 的元素操作 191 第5章 关联式容器(associated containers) 197 5.1 树的导览 199 5.1.1 二元搜寻树(binary search tree) 200 5.1.2 平衡二元搜寻树(balanced binary search tree) 203 5.1.3 avl tree(adelson-velskii-landis tree) 203 5.1.4 单旋转(single rotation) 205 5.1.5 双旋转(double rotation) 206 5.2 rb-tree(红黑树) 208 5.2.1 插入节点 209 5.2.2 一个由上而下的程序 212 5.2.3 rb-tree 的节点设计 213 5.2.4 rb-tree 的迭代器 214 5.2.5 rb-tree 的数据结构 218 5.2.6 rb-tree 的构造与内存管理 221 5.2.7 rb-tree 的元素操作 223 元素插入动作 insert_equal 223 元素插入动作 insert_unique 224 真正的插入执行程序 __insert 224 调整rb-tree(旋转及改变颜色) 225 元素的搜寻 find 229 5.3 set 233 5.4 map 237 5.5 multiset 245 5.6 multimap 246 5.7 hashtable 247 5.7.1 hashtable 概述 247 线性探测(linear probing) 249 二次探测(quadratic probing) 251 分离链(separate chaining) 253 5.7.2 hashtable 的桶子(buckets)与节点(nodes) 253 5.7.3 hashtable 的迭代器 254 5.7.4 hashtable 的数据结构 256 5.7.5 hashtable 的构造与内存管理 258 插入动作(insert)与表格重整(resize) 259 判知元素的落脚处(bkt_num) 262 复制(copy_from)和整体删除(clear) 263 5.7.6 hashtable 运用实例(find, count) 264 5.7.7 hash functions 268 5.8 hash_set 270 5.9 hash_map 275 5.10 hash_multiset 279 5.11 hash_multimap 282 第6章 算法(algorithms) 285 6.1 算法概观 285 6.1.1 算法分析与复杂度表示 o( ) 286 6.1.2 stl算法总览 288 6.1.3 mutating algorithms - 会改变操作对象之值 291 6.1.4 nonmutating algorithms - 不改变操作对象之值 292 6.1.5 stl算法的一般形式 292 6.2 算法的泛化过程 294 6.3 数值算法 [stl_numeric.h] 298 6.3.1 运用实例 298 6.3.2 accumulate 299 6.3.3 adjacent_difference 300 6.3.4 inner_product 301 6.3.5 partial_sum 303 6.3.6 power 304 6.3.7 itoa 305 6.4 基本算法 [stl_algobase.h] 305 6.4.1 运用实例 305 6.4.2 equal 307 fill 308 fill_n 308 iter_swap 309 lexicographical_compare 310 max, min 312 mismatch 313 swap 314 6.4.3 copy,强化效率无所不用其极 314 6.4.4 copy_backward 326 6.5 set 相关算法(应用于有序区间) 328 6.5.1 set_union 331 6.5.2 set_intersection 333 6.5.3 set_difference 334 6.5.4 set_symmetric_difference 336 6.6 heap算法:make_heap, pop_heap, push_heap, sort_heap 338 6.7 其它算法 338 6.7.1 单纯的数据处理 338 adjacent_find 343 count 344 count_if 344 find 345 find_if 345 find_end 345 find_first_of 348 for_each 348 generate 349 generate_n 349 includes (应用于有序区间) 349 max_element 352 merge (应用于有序区间) 352 min_element 354 partition 354 remove 357 remove_copy 357 remove_if 357 remove_copy_if 358 replace 359 replace_copy 359 replace_if 359 replace_copy_if 360 reverse 360 reverse_copy 361 rotate 361 rotate_copy 365 search 365 search_n 366 swap_ranges 369 transform 369 unique 370 unique_copy 371 6.7.2 lower_bound (应用于有序区间) 375 6.7.3 upper_bound (应用于有序区间) 377 6.7.4 binary_search (应用于有序区间) 379 6.7.5 next_permutation 380 6.7.6 prev_permutation 382 6.7.7 random_shuffle 383 6.7.8 partial_sort / partial_sort_copy 386 6.7.9 sort 389 6.7.10 equal_range(应用于有序区间) 400 6.7.11 inplace_merge(应用于有序区间) 403 6.7.12 nth_element 409 6.7.13 merge sort 411 第7章 仿函数(functor,另名 函数对象function objects) 413 7.1 仿函数(functor)概观 413 7.2 可配接(adaptable)的关键 415 7.2.1 unary_function 416 7.2.2 binary_function 417 7.3 算术类(arithmetic)仿函数 418 plus, minus, multiplies, divides, modulus, negate, identity_element 7.4 关系类(relational)仿函数 420 equal_to, not_equal_to, greater, greater_equal, less, less_equal 7.5 逻辑运算类(logical)仿函数 422 logical_and, logical_or, logical_not 7.6 证同(identity)、选择(select)、投射(project) 423 identity, select1st, select2nd, project1st, project2nd 第8章 配接器(adapter) 425 8.1 配接器之概观与分类 425 8.1.1 应用于容器,container adapters 425 8.1.2 应用于迭代器,iterator adapters 425 运用实例 427 8.1.3 应用于仿函数,functor adapters 428 运用实例 429 8.2 container adapters 434 8.2.1 stack 434 8.2.2 queue 434 8.3 iterator adapters 435 8.3.1 insert iterators 435 8.3.2 reverse iterators 437 8.3.3 stream iterators (istream_iterator, ostream_iterator) 442 8.4 function adapters 448 8.4.1 对传回值进行逻辑否定:not1, not2 450 8.4.2 对参数进行系结(绑定):bind1st, bind2nd 451 8.4.3 用于函数合成:compose1, compose2(未纳入标准) 453 8.4.4 用于函数指针:ptr_fun 454 8.4.5 用于成员函数指针:mem_fun, mem_fun_ref 456 附录a 参考资料与推荐读物(bibliography) 461 附录b 侯捷网站简介 471 附录c stlport 的移植经验(by 孟岩) 473 borland c++builder 5 474 microsoft visual c++ 6.0 477 索引 481

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值