zoukankan      html  css  js  c++  java
  • STL 概览

    概述

    网上常见的说法是 STL 包含六大组件。

    • 容器 container
    • 算法 algorthm
    • 迭代器 iterator
    • 仿函数 function object
    • 适配器 adaptor
    • 空间配置器 allocator

    抄袭链接:https://www.jianshu.com/p/497843e403b4

    容器

    下面列举几种常见的容器:

    • vector 容器
    • deque 双端数组
    • stack 栈模型
    • queue 队列模型
    • list 链表模型
    • priotriy_queue 优先级队列
    • set 与 multiset 容器
    • map 与 multimap 容器
    • string

    算法

    STL 中的算法可以分为以下几类。(网上抄的,链接找不到了)

    • 只读算法:查找和计数
    • 可变序列算法:复制、变换、替换、填充、移除和随机生成
    • 排序算法
    • 比较算法
    • 堆算法
    • 各个容器特有算法

    迭代器

    迭代器提供了用于遍历元素的 “指针”,容器和算法之间可以通过迭代器联系起来。迭代器有“前向”和“后向”的区别,有“常量”和“非常量”的区别。对于迭代器,++i 通常是要比 i++ 要快的。比如 vector 中实现为这个样子:

    _Vector_iterator& operator++() noexcept {
        _Mybase::operator++();
        return *this;
    }
    
    _Vector_iterator operator++(int) noexcept {
        _Vector_iterator _Tmp = *this;
        _Mybase::operator++();
        return _Tmp;
    }
    

    仿函数

    在没有 lambda std::function, 之前通过重载 operator() 来实现类似函数的行为。比如下面的 plus,实际上是一个结构体,重载了圆括号操作符,它的对象就可以像函数一样被调用了。

    // 库函数中 plus 的实现
    // STRUCT TEMPLATE plus
    template <class _Ty = void>
    struct plus {
        _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty _FIRST_ARGUMENT_TYPE_NAME;
        _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty _SECOND_ARGUMENT_TYPE_NAME;
        _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty _RESULT_TYPE_NAME;
    
        _NODISCARD constexpr _Ty operator()(const _Ty& _Left, const _Ty& _Right) const {
            return _Left + _Right;
        }
    };
    
    // 自己实现一个
    template <typename T, typename Container>
    struct Sum
    {
    	Sum() {
    		cout << "Sum construct" << endl;
    	}
    	T operator()(Container container) {
    		T acc = T(0);
    		for (auto x : container) {
    			acc += x;
    		}
    		return acc;
    	}
    };
    
    int main() {
    	vector<int> arr = { 1, 2, 3, 5 };
    	auto x = accumulate(arr.cbegin(), arr.cend(), 0, plus<int>());
    	Sum<decltype(arr)::value_type, decltype(arr)> sum_functor;
    	Sum<decltype(arr)::value_type, decltype(arr)> sum_functor1{};
    	Sum<decltype(arr)::value_type, decltype(arr)> sum_functor2 = Sum<decltype(arr)::value_type, decltype(arr)>();
    	Sum<decltype(arr)::value_type, decltype(arr)> sum_functor3(); // 这个是啥语法啊
    	auto y = sum_functor(arr);
    	cout << x << " " << y << endl;
    	return 0;
    }
    

    适配器

    一种设计模型。这就好像香港的充电器需要使用一个适配器才可以插到插座上。

    STL 当中的 stack, queue, priority_queue 三种容器就是适配器。对于适配器,它可以接收一个容器,然后提供 stack 需要的接口,比如 push, pop 等方法。内部实现就是调用容器的方法去 push, pop。

    template <class _Ty, class _Container = deque<_Ty>>
    class stack;
    
    template <class _Ty, class _Container>
    class stack {
    public:
        using value_type      = typename _Container::value_type;
        using reference       = typename _Container::reference;
        using const_reference = typename _Container::const_reference;
        using size_type       = typename _Container::size_type;
        using container_type  = _Container;
    
        static_assert(is_same_v<_Ty, value_type>, "container adaptors require consistent types");
    
        stack() = default;
    
        explicit stack(const _Container& _Cont) : c(_Cont) {}
        
        // ...
    }
    

    分配器

    负责内存管理,分配内存。allocator 提供了几个方法进行分配回收内存和对象构造析构:allocate, deallocate, construct, destory, address, max_size。如果调用 deallocate 没有调用 destory,那么不会调用类的析构函数。

    参考:https://vimsky.com/zh-tw/examples/usage/stdallocator-in-cpp-with-examples.html

    class Apple {
    public:
    	Apple() {
    		cout << "apple construct" << endl;
    	}
    	~Apple() {
    		cout << "apple desstruct" << endl;
    	}
    };
    
    int main() {
    	allocator<Apple> apple_alloc;
    	Apple* apples = apple_alloc.allocate(10);
    	apple_alloc.construct(apples);
    	apple_alloc.construct(apples + 1);
    	apple_alloc.destroy(apples);
    	apple_alloc.destroy(apples + 1);
    	return 0;
    }
    

    vector 中的 reverse 方法就是调用了 allocator 去分配内存。

    void reserve(_CRT_GUARDOVERFLOW const size_type _Newcapacity) {
        // increase capacity to _Newcapacity (without geometric growth), provide strong guarantee
        if (_Newcapacity > capacity()) { // something to do (reserve() never shrinks)
            if (_Newcapacity > max_size()) {
                _Xlength();
            }
    
            _Reallocate_exactly(_Newcapacity);
        }
    }
    
    void _Reallocate_exactly(const size_type _Newcapacity) {
        // set capacity to _Newcapacity (without geometric growth), provide strong guarantee
        auto& _My_data    = _Mypair._Myval2;
        pointer& _Myfirst = _My_data._Myfirst;
        pointer& _Mylast  = _My_data._Mylast;
    
        const auto _Size = static_cast<size_type>(_Mylast - _Myfirst);
    
        const pointer _Newvec = _Getal().allocate(_Newcapacity);
    
        _TRY_BEGIN
        _Umove_if_noexcept(_Myfirst, _Mylast, _Newvec);
        _CATCH_ALL
        _Getal().deallocate(_Newvec, _Newcapacity);
        _RERAISE;
        _CATCH_END
    
        _Change_array(_Newvec, _Size, _Newcapacity);
    }
    
  • 相关阅读:
    在定义SharePoint列表的SPD数据视图的时候需要注意的问题
    如何自定义改变SharePoint 中列表Web部件中所有行某列中的固定值为图片或其它HTML代码
    [C#3] 1扩展方法
    特效编辑器开发手记2——cocos2dx粒子系统的plist文件 深圳
    让人死去活来的cocos2dx安卓开发环境搭建(windows+eclipse+ndk 不用cygwin)【上图】 深圳
    《疾风》开发手记:NxOgre最新版本的搭建20111020 深圳
    Linux 操作系统下CPU多核心的绑定 深圳
    巧用Unix时间戳 深圳
    AS3加载AS2的swf文件报错 深圳
    GLUT函数说明(转载) 深圳
  • 原文地址:https://www.cnblogs.com/zzk0/p/15549573.html
Copyright © 2011-2022 走看看