IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++【STL】 | 容器、函数、迭代器配接器 -> 正文阅读

[C++知识库]C++【STL】 | 容器、函数、迭代器配接器

一、简介

为STL组件提供更加灵活的用法,可应用于函数、容器、迭代器;

二、容器配接器

stack,是在deque容器进行封装;
queue,是在deque上进行封装;

三、迭代器配接器

- insert iterators:插入迭代器,提供尾插、首插、以及任意位置插入的方法;
- reverse iterators:将正向的迭代器逆转;
- iostream iterators:将迭代器绑定到iostream上;
	- ostream_iterator:输出;
	- istream_iterator:输入;

insert Iterator

template<class Container>
class insert_iterator{
protected:
    Container* container;       /* 容器 */
    typename Container::iterator iter;  /* 迭代器类型 */

public:
    typedef output_iterator_tag iterator_category;
    typedef void value_type;
    typedef void difference_type;
    typedef void pointer;
    typedef void reference;

    explicit insert_iterator(Container& x, typename Container::iterator i) : container(&x), iter(i) {}
    insert_iterator<Container>&
    operator=(const typename Container::value_type& value) {
        container->insert(iter, value);
        return *this;
    }

    insert_iterator<Container>& operator*() { return *this; }
    insert_iterator<Container>& operator++() { return *this; }
    insert_iterator<Container>& operator++(int) { return *this; }
};

template<class Container, class Iterator>
inline insert_iterator<Container> iterator(Container& x, Iterator i) {
    return insert_iterator<Container> (x, iter(i));
}

back insert iterator

template<class Container>
class back_insert_iterator{
protected:
    Container* container;   // 传入的容器

public:
    // 定义型别
    typedef output_iterator_tag iterator_category;
    typedef void value_type;
    typedef void difference_type;
    typedef void pointer;
    typedef void reference;

    /** 与容器绑定 */
    explicit back_insert_iterator(Container& x) : container(x) {}
    /** 赋值操作 */
    back_insert_iterator<Container>&
    operator=(const typename Container::value_type& value) {
        container->push_back(value);
        return *this;
    }

    /** 关闭运算符 */
    back_insert_iterator<Container>& operator*() { return *this; }
    back_insert_iterator<Container>& operator++() { return *this; }
    back_insert_iterator<Container>& operator++(int) { return *this; }
};

/** 封装 */
template<class Container>
inline back_insert_iterator<Container> back_insert(Container& x) {
    return back_insert_iterator<Container> (x);
}

front insert_iterator


template<class Container>
class front_insert_iterator{
protected:
    Container* container;   /* 容器 */

public:
    // 类型型别
    typedef output_iterator_tag iterator_category;
    typedef void value_type;
    typedef void difference_type;
    typedef void pointer;
    typedef void reference;

    /** 与容器绑定 */
    explicit front_insert_iterator(Container& x) : container(x) {}
    /** 赋值操作 */
    front_insert_iterator<Container>&
    operator=(const typename Container::value_type& value) {
        container->push_front(value);
        return *this;
    }

    /** 关闭运算符 */
    front_insert_iterator<Container>& operator*() { return *this; }
    front_insert_iterator<Container>& operator++() { return *this; }
    front_insert_iterator<Container>& operator++(int) { return *this; }
};

/** 封装 */
template<class Container>
inline front_insert_iterator<Container> front_iterator(Container& x) {
    return front_insert_iterator<Container> (x);
}

reverse iterator

template<class Iterator>
class reverse_iterator {
protected:
    Iterator current;

public:
    // 对应正向迭代器型别
    typedef typename iterator_traits<Iterator>::iterator_category iterator_category;
    typedef typename iterator_traits<Iterator>::value_type value_type;
    typedef typename iterator_traits<Iterator>::difference_type difference_type;
    typedef typename iterator_traits<Iterator>::pointer pointer;
    typedef typename iterator_traits<Iterator>::reference reference;

    typedef Iterator iterator_type;     // 正向迭代器
    typedef reverse_iterator<Iterator> self;    // 逆向迭代器

public:
    reverse_iterator() {}
    explicit reverse_iterator(iterator_type x) : current(x) {}
    reverse_iterator(const self& x) : current(x.current) {}

    iterator_type base() const { return current; }

    reference operator*() const {
        Iterator tmp = current;
        return *--tmp;
    }
    pointer operator->() const { return &(operator*()); }

    self& operator++() {
        --current;
        return *this;
    }

    self operator++(int) {
        self tmp = *this;
        --current;
        return tmp;
    }

    self& operator--() {
        ++current;
        return *this;
    }

    self operator--(int) {
        self tmp = *this;
        ++current;
        return *this;
    }

    self operator+(difference_type n) const {
        return self(current-n);
    }

    self& operator+=(difference_type n) const {
        current -= n;
        return *this;
    }
    self operator-(difference_type n) const {
        return self(current + n);
    }

    self& operator-=(difference_type n) const  {
        current += n;
        return *this;
    }
    reference operator[](difference_type n) const { return *(*this + n); }
};

istream iterator

template<class T, class Distance = ptrdiff_t>
class istream_iterator {
    template<>
    friend bool operator==(const istream_iterator<T, Distance& x>,
            const istream_iterator<T, Distance& y>);

protected:
    istream* stream;
    T value;
    bool end_marker;

    void read() {
        /* 判断读入的状态是否有改变,当读取到结尾时为false */
        end_marker = (*stream) ? true : false;
        if(end_marker) *stream >> value;
        end_marker = (*stream) ? true : false;
    }

public:
    typedef intput_iterator_tag iterator_category;
    typedef T value_type;
    typedef Distance difference_type;
    typedef const T* pointer;
    typedef const T& reference;

    istream_iterator() : stream(&cin), end_marker(false) { }
    istream_iterator(istream& s) : stream(&s) { read(); }
    reference operator*() const  { return value; }
    pointer operator->() const { return &(operator*()); }

    istream_iterator<T,Distance>& operator++() {
        read();
        return *this;
    }

    istream_iterator<T, Distance> operator++(int) {
        istream_iterator<T, Distance> tmp = *this;
        read();
        return tmp;
    }
};

ostream iteraotr

template<class T>
class ostream_iterator {
protected:
    ostream* stream;
    const char* string;

public:
    typedef ontput_iterator_tag iterator_category;
    typedef void value_type;
    typedef void difference_type;
    typedef void  pointer;
    typedef void  reference;

    ostream_iterator(ostream& s) : stream(&s), string(0) { }
    ostream_iterator(ostream& s, const char* c) : stream(&s), string(c) { }

    ostream_iterator<T>& operator=(const T& value) {
        *stream << value;
        if(string) *stream << string ;
        return *this;
    }

    ostream_iterator<T>& operator*() { return *this; }
    ostream_iterator<T>& operator++() { return *this; }
    ostream_iterator<T>& operator++(int) { return *this; }

};

四、函数配接器

能给函数提供绑定、组合、修饰能力;
【注意】:会改变参数的和不改变参数的不能搭配使用;

1、自定义函数如何才能有配接能力

若为一元仿函数则必须继承unarg_funtion,二元需要继承binary_function,成员函数必须与mem_fun处理;

成员函数配接器:mem_fun_ref

template <class S, class T>
  mem_fun_ref_t<S,T> mem_fun_ref (S (T::*f)())
  { return mem_fun_ref_t<S,T>(f); }

func:将成员函数转换为函数对象,引用版本,`mem_fun`为指针版;

eg:
	for_each(arr.begin(), end.begin(), mem_fun_ref(&Func::pprint));
	即调用Func中的const成员函数pprint,打印arr的所有元素;

==> 若需要传入参数,可使用bind2nd进行绑定传参;

【为什么使用配接器进行函数传参?】
> 使用配接器能够将`原本针对某个元素的函数调用动作`转为`调用被传递的成员函数`;

非成员函数配接器:ptr_fun

template <class Arg, class Result>
  pointer_to_unary_function<Arg,Result> ptr_fun (Result (*f)(Arg));

template <class Arg1, class Arg2, class Result>
  pointer_to_binary_function<Arg1,Arg2,Result> ptr_fun (Result (*f)(Arg1,Arg2));
  
func:将函数指针转换为函数对象;
	- 当时用的仿函数需要提供特殊的型别;
	- 当使用一个双参数全局函数,想当做单参数使用,并结合bind2nd;
void print(int i) {
    cout << i << " ";
}

class Int{
public:
    int m_i;
    Int(int i) : m_i(i) {}
    void print() const { cout << "[" << m_i << "]"; }
};

void test_men_fun() {
    ostream_iterator<int> outite(cout, " ");
    vector<int> vc = {1, 3, 7, 8, 10};

    for_each(vc.begin(), vc.end(), ptr_fun(print));
    cout << endl;

    Int t1(3), t2(7), t3(20);
    vector<Int> vvc = { t1, t2, t3 };
    for_each(vvc.begin(), vvc.end(), mem_fun_ref(&Int::print));
}

2、函数绑定

函数绑定:bind2nd

template <class Operation, class T>
  binder2nd<Operation> bind2nd (const Operation& op, const T& x);

func:绑定第二参数;
eg:
	find_if(arr.begin(), arr.end(), bind2nd(less<int>(), 4));
	即查找arr中【<=4】的数;

函数绑定:bind1st

template <class Operation, class T>
  binder1st<Operation> bind1st (const Operation& op, const T& x);

func:绑定第一参数;

函数绑定:bind

template <class Fn, class... Args>
bind (Fn&& fn, Args&&... args);
template <class Ret, class Fn, class... Args>
bind (Fn&& fn, Args&&... args);

func:C++11后提供,提供的模板可接受多种参数,也可接受返回值类型类型;
通过使用占位符对函数参数进行传递;在std::placeholders下;
【注意】:_1即第一参数,_2即第二参数,和位置没有关系;
void test_bind() {
    using namespace std::placeholders;
    vector<int> vc{1, 4, 6, 7, 8};
    int num = count_if(vc.begin(), vc.end(), binder1st(less<int>(), 4));
    cout << "4<=x num: " << num << endl;

    num = count_if(vc.begin(), vc.end(), binder2nd(less<int>(), 4));
    cout << "x<=4 num: " << num << endl;

    auto fn = bind(less<int>(), _1, 4);
    num = count_if(vc.begin(), vc.end(), fn);
    cout << "x<=4 num: " << num << endl;

    auto fn_1 = bind([](int x, int y){ return x < y; }, _1, 10);
    cout << "20 < 10: " << (fn_1(20) ? "y": "n") << endl;

    auto fn_2 = bind([](int x, int y){ return x < y; }, _2, _1);
    cout << "20 < 10: " << (fn_2(20, 10) ? "y": "n") << endl;
}

在这里插入图片描述

3、辅助配接器

将其中的函数运算结果作为另一个函数的参数输入

/*----------------------------------------------------------------------
	> File Name: test.cpp
	> Author: Jxiepc
	> Mail: Jxiepc
	> Created Time: Mon 07 Mar 2022 05:46:53 PM CST
----------------------------------------------------------------------*/

#include <iostream>
#include <functional>
#include <iterator>
#include <algorithm>
#include <vector>

using namespace std;



template<class T1, class T2>
class compose_f_gx_t : public std::unary_function<typename T2::argument_type,
    typename T1::result_type>{

private:
    T1 op1;
    T2 op2;
public:
    compose_f_gx_t(const T1& o1, const T2& o2)
        :op1(o1), op2(o2) {
        }
    typename T1::result_type
    operator()(const typename T2::argument_type& x) const  {
        return op1(op2(x));
    }

};

template<class T1, class T2>
inline compose_f_gx_t<T1, T2>
compose_f_gx(const T1& o1, const T2& o2) {
    return compose_f_gx_t<T1, T2>(o1, o2);
}


void test() {
    std::vector<int> vc;

    for(int i=0; i<9; ++i) {
        vc.push_back(i);
    }
    /** 将会先执行每个元素加10,后再对每个元素乘5 */
    transform(vc.begin(), vc.end(),
            ostream_iterator<int>(cout, " "),
            compose_f_gx(bind2nd(multiplies<int>(), 5),
                bind2nd(plus<int>(), 10)));
    std::cout << std::endl;
}

int main(int argc, char* argv[])
{
    test();
    return 0;
}

在这里插入图片描述

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-22 18:17:37  更:2022-04-22 18:19:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:44:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码