[c++] Let's dissect STL
源码在哪里
gcc & g++
gcc 最开始的时候是 GNU C Compiler, 如你所知,就是一个c编译器。但是后来因为这个项目里边集成了更多其他不同语言的编译器,GCC就代表 the GNU Compiler Collection,所以表示一堆编译器的合集。 g++则是GCC的c++编译器。
现在你在编译代码时调用的gcc,已经不是当初那个c语言编译器了,更确切的说他是一个驱动程序,根据代码的后缀名来判断调用c编译器还是c++编译器 (g++)。比如你的代码后缀是*.c,他会调用c编译器还有linker去链接c的library。如果你的代码后缀是cpp, 他会调用g++编译器,当然library call也是c++版本的。
源代码下载
Official web: GCC: Anonymous read-only Git access
Download source code: http://ftp.gnu.org/gnu/gcc/
STL相关文件
通过模板写的 .tcc文件.
gcc-4.9.4$ find ./libstdc++-v3/include/bits/ -name "*.tcc"
./libstdc++-v3/include/bits/basic_ios.tcc ./libstdc++-v3/include/bits/valarray_array.tcc ./libstdc++-v3/include/bits/fstream.tcc ./libstdc++-v3/include/bits/locale_classes.tcc ./libstdc++-v3/include/bits/streambuf.tcc ./libstdc++-v3/include/bits/sstream.tcc ./libstdc++-v3/include/bits/regex.tcc ./libstdc++-v3/include/bits/locale_facets.tcc ./libstdc++-v3/include/bits/vector.tcc ./libstdc++-v3/include/bits/forward_list.tcc ./libstdc++-v3/include/bits/locale_facets_nonio.tcc ./libstdc++-v3/include/bits/regex_compiler.tcc ./libstdc++-v3/include/bits/random.tcc ./libstdc++-v3/include/bits/regex_automaton.tcc ./libstdc++-v3/include/bits/regex_executor.tcc ./libstdc++-v3/include/bits/istream.tcc ./libstdc++-v3/include/bits/basic_string.tcc ./libstdc++-v3/include/bits/deque.tcc ./libstdc++-v3/include/bits/regex_scanner.tcc ./libstdc++-v3/include/bits/ostream.tcc ./libstdc++-v3/include/bits/list.tcc
相关的头文件.
jeffrey@unsw-ThinkPad-T490:gcc-4.9.4$ find . -name "stl_*"
./libstdc++-v3/include/bits/stl_heap.h ./libstdc++-v3/include/bits/stl_tree.h ./libstdc++-v3/include/bits/stl_multimap.h ./libstdc++-v3/include/bits/stl_list.h ./libstdc++-v3/include/bits/stl_deque.h ./libstdc++-v3/include/bits/stl_iterator.h ./libstdc++-v3/include/bits/stl_construct.h ./libstdc++-v3/include/bits/stl_set.h ./libstdc++-v3/include/bits/stl_algo.h ./libstdc++-v3/include/bits/stl_function.h ./libstdc++-v3/include/bits/stl_uninitialized.h ./libstdc++-v3/include/bits/stl_stack.h ./libstdc++-v3/include/bits/stl_tempbuf.h ./libstdc++-v3/include/bits/stl_relops.h ./libstdc++-v3/include/bits/stl_bvector.h ./libstdc++-v3/include/bits/stl_multiset.h ./libstdc++-v3/include/bits/stl_iterator_base_funcs.h ./libstdc++-v3/include/bits/stl_algobase.h ./libstdc++-v3/include/bits/stl_queue.h ./libstdc++-v3/include/bits/stl_map.h ./libstdc++-v3/include/bits/stl_pair.h ./libstdc++-v3/include/bits/stl_numeric.h ./libstdc++-v3/include/bits/stl_iterator_base_types.h ./libstdc++-v3/include/bits/stl_raw_storage_iter.h ./libstdc++-v3/include/bits/stl_vector.h
框架理解
概览图
阅读笔记
-
提炼总结:概览
Ref: 《STL源码剖析》提炼总结:概览
STL是一个标准,只规定了STL的接口,内部实现没有要求。STL有许多实现版本,PJ STL(被Visual C++采用),RW STL等。
SGI STL版本注释丰富,结构清晰,可读性最强,同时它也被GCC采用,所以是最流行的版本。
注意,SGI STL并不是原封不动的被用于GCC,所以在GCC中使用STL可能会和SGI STL有一些微小的区别。
Goto: SGI STL DOCUMENTATION
STL分为六大组件:
-
- 容器(container):常用数据结构,大致分为两类,序列容器,如vector,list,deque,关联容器,如set,map。在实现上,是类模板(class template)
- 迭代器(iterator):一套访问容器的接口,行为类似于指针。它为不同算法提供的相对统一的容器访问方式,使得设计算法时无需关注过多关注数据。(“算法”指广义的算法,操作数据的逻辑代码都可认为是算法)
- 算法(algorithm):提供一套常用的算法,如sort,search,copy,erase … 在实现上,可以认为是一种函数模板(function template)。
- 配置器(allocator):为容器提供空间配置和释放,对象构造和析构的服务,也是一个class template。
- 仿函数(functor):作为函数使用的对象,用于泛化算法中的操作。
- 配接器(adapter):将一种容器修饰为功能不同的另一种容器,如以容器vector为基础,在其上实现stack,stack的行为也是一种容器。这就是一种配接器。除此之外,还有迭代器配接器和仿函数配接器。
-
提炼总结:空间配置器(allocator)
Ref:《STL源码剖析》提炼总结:空间配置器(allocator)
使用自己编写的allocator来为vector分配空间:
#include <vector>
int main() { std::vector<int, my_alloc::allocator<int>> v; // Do something; return 0; }
一个最简单的allocator实现,它是符合STL标准的
#ifndef _MYALLOC_ #define _MYALLOC_ #include <new> #include <cstddef> #include <cstdlib> #include <climits> #include <iostream> namespace my_alloc { // allocate的实际实现,简单封装new,当无法获得内存时,报错并退出 template <class T> inline T* _allocate(ptrdiff_t size, T*) { set_new_handler(0); T* tmp = (T*)(::operator new((size_t)(size * sizeof(T)))); if (tmp == 0) { cerr << "out of memory" << endl; exit(1); } return tmp; } // deallocate的实际实现,简单封装delete template <class T> inline void _deallocate(T* buffer) { ::operator delete(buffer); } // construct的实际实现,直接调用对象的构造函数 template <class T1, class T2> inline void _construct(T1* p, const T2& value) { new(p) T1(value); } // destroy的实际实现,直接调用对象的析构函数 template <class T> inline void _destroy(T* ptr) { ptr->~T(); } template <class T> class allocator { public: typedef T value_type; typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; typedef size_t size_type; typedef ptrdiff_t difference_type; // 构造函数 allocator(){ return; } template <class U> allocator(const allocator<U>& c){} // rebind allocator of type U template <class U> struct rebind { typedef allocator<U> other; }; // allocate,deallocate,construct和destroy函数均调用上面的实际实现 // hint used for locality. ref.[Austern],p189 pointer allocate(size_type n, const void* hint = 0) { return _allocate((difference_type)n, (pointer)0); } void deallocate(pointer p, size_type n) { _deallocate(p); } void construct(pointer p, const T& value) { _construct(p, value); } void destroy(pointer p) { _destroy(p); } pointer address(reference x) { return (pointer)&x; } const_pointer const_address(const_reference x) { return (const_pointer)&x; } size_type max_size() const { return size_type(UINT_MAX / sizeof(T)); } }; } // end of namespace myalloc #endif // _MYALLOC_
-
C++之STL源码剖析:迭代器 Iterator
Ref: C++之STL源码剖析
OOP&GP
-
- 面向对象:封装是基础,继承是手段,多态是目的。
- 泛型编程:参数化类型是基础,模板是手段,通用是目的。
- 面向对象的编程依赖运行时多态,泛型编程是编译时多态。
这里用List作为例子,数据结构是:
template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
class list : protected _List_base<_Tp, _Alloc> { // concept requirements typedef typename _Alloc::value_type _Alloc_value_type; __glibcxx_class_requires(_Tp, _SGIAssignableConcept) __glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept) typedef _List_base<_Tp, _Alloc> _Base; typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; typedef typename _Base::_Node_alloc_type _Node_alloc_type; public: typedef _Tp value_type; typedef typename _Tp_alloc_type::pointer pointer; typedef typename _Tp_alloc_type::const_pointer const_pointer; typedef typename _Tp_alloc_type::reference reference; typedef typename _Tp_alloc_type::const_reference const_reference; typedef _List_iterator<_Tp> iterator; typedef _List_const_iterator<_Tp> const_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator; typedef std::reverse_iterator<iterator> reverse_iterator; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef _Alloc allocator_type;
... ...
首先,节点如何定义?
template <class T>
struct __list_node {
typedef void* void_pointer; void_pointer prev; void_pointer next; T data; };
其次,迭代器一般都放在容器中实现,针对某一类容器实现各自的迭代器.
vector<int>::iterator iter; // 定义一个正向迭代器
可见,::iterator的实现细节如下.
template<class T, class Ref, class Ptr>
struct __list_iterator {
typedef __list_iterator<T, T&, T*> iterator; typedef __list_iterator<T, Ref, Ptr> self; typedef __list_node<T>* link_type; __list_iterator(link_type x) : node(x) { } __list_iterator() { } __list_iterator(const iterator& x) : node(x.node) { } link_type node; bool operator==(const self& x) const { return node == x.node; } bool operator!=(const self& x) const { return node == x.node; } reference operator*() const { return (*node).data; } pointer operator->() const { return &(operator*()); } self& operator++() { node = (link_type)((*node).next); return *this; } self operator++(int) { self tmp = *this; ++*this; return tmp; } self& operator--() { node = (link_type)((*node).prev); return *this; } self operator--(int) { self tmp = *this; --*this; return tmp; } }
End.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律