美文网首页
第十周 C++标准库 体系结构与内核分析 Boolan 侯捷

第十周 C++标准库 体系结构与内核分析 Boolan 侯捷

作者: 一般的路人丙 | 来源:发表于2017-03-30 15:49 被阅读0次

    0. 作业的启示

    作业要求:编写一个Sink迭代器,同时可以完成inserter迭代器和打印数值的功能

    第一个版本

    思路

    既然是inserter的加强版,那么就先写一个inserter,然后加一个打印数值的功能。

    编写

    先把课件上的代码抄下来,然后试着编译一下,提示找不到value_type。然后看了一下库里面的inserter,发现继承了iterator类,所以按着改了一下,调通。
    然后就是在什么时候打印数值,有两个位置可以打印,一个是在调用inserter函数的时候,另一个是在操作符重载的时候。
    一开始以为,只要在调用inserter函数,就会打印数值,所以只需要在inserter里面加一个打印函数就可以了。

    template<typename Container, typename Iterator>
    inline Sink_iterator<Container>
    Sink(Container &x, Iterator it) {
        printContent(x);
        Sink_iterator<Container> yy(x,
                                 typename Container::iterator(it));
        return yy;
    }
    

    试了以后发现不对,这样子只能打印最初的一次,可能是因为copy的实现方式不同。这时就需要在操作符重载的时候再打印一次。

        Sink_iterator &
        operator=(const typename Container::value_type &value) {
            *iiter=value;
            printContent(*container);
            return *this;
        
    

    第二个版本

    第一个版本就是重写了一遍inserter,感觉并不像是写作业啊,因为没什么技术含量。
    所以又开始想第二个版本。

    思路

    想了想,既然是在inserter上面添加一个功能,那是不是应该再写一个适配器?
    那么可以考虑继承一下insert_iterator

    问题

    编写的过程很顺利,不过运行上就发现不对了,因为标准库里面的insert_iterator的操作符重载并不是虚函数,导致继承后没有办法进行操作符重载。试了好几次,并没有发现解决办法。

    第三个版本

    感觉是思路的问题,不用继承,可以考虑用引用。

    思路

    写一个子类继承iterator,在子类中建立一个insert_iterator,这时候可以重载这个子类的操作符。

    编写

    所有实现insert的功能都可以使用insert_iterator的功能,比如说操作符重载里面的功能就可以直接使用操作符重载。

            iter = container->insert(iter, value);
            ++iter;
            // 改成下面这样 
            *iiter=value;
    

    但是出现了一个问题,因为打印的函数不是insert_iterator的友元,所以不能访问里面的迭代器,这就没办法打印了。没想出解决方案,于是在传递迭代器之前把这个值保存一下。因此比第一个版本多占用了一些空间,以后可以考虑这里的改进方法。

    比较

    第三个版本在这里看并不好,因为效率不会很好。
    但是如果这里不是inserter这样的适配器,比如说更复杂很多,那么第三个版本就会显得重写的代码更少一些。

    一个万用的 Hash Function

    #include <functional>
    class Customer {
    ...
    };
    
    class CustomerHash{
    public:
        std::size_t operator() (const Customer&c) const {
            return ...
        }
    };
    
    unordered_set<Customer,CustomerHash> custset;
    

    TR1中的一个函数hash_val

    template <typename... Types>
    inline size_t hash_val(const Type&... args){
        size_t seed=0;
        hash_val(seed,args...);
        return seed;
    }
    
    template <typename T,typename... Types>
    

    每次取出一个。

    以struct hash 偏特化形式实现 Hash Function

    tuple,用例

    get<0>(t1)取第一个数值

    tie(i1,f1,s1)=t3;// 绑定三个数值
    

    任意数值的组合

    type traits

    对于没有指针的class
    析构函数
    拷贝构造函数
    拷贝赋值函数
    都不重要
    有指针的需要考虑

    type traits, 测试

    Zoo&&
    move constructor
    搬移赋值?
    =default是什么意思?
    =delete

    写了构造函数,编译器就不会给默认构造函数。

    cout

    cout 根据输入内容的类型做了不同的操作符重载的特化

    movable 元素对于 内置类型 速度效能的影响

    vector
    因为要成长,所以要复制或移动很多次
    list
    map
    set
    deque
    不涉及增长,所以差别不大

    如何写一个moveable class

    深拷贝是我们欢迎的,而浅拷贝是很危险的,浅拷贝就是move的动作
    深拷贝就是既拷贝指针,又拷贝内容
    movecopy &&
    析构也有差别

    测试函数

    相关文章

      网友评论

          本文标题:第十周 C++标准库 体系结构与内核分析 Boolan 侯捷

          本文链接:https://www.haomeiwen.com/subject/zmsgnttx.html