zoukankan      html  css  js  c++  java
  • C++标准程序库学习笔记

    1、辅助性“比较操作符”

    有四个template functions,分别定义了!=, >, <=, >=四个比较操作符,它们都是利用==, <来完成的,定义于<utility>

        namespace rel_ops
            {    // nested namespace to hide relational operators from std
    template<class _Ty> inline
        bool  operator!=(const _Ty& _Left, const _Ty& _Right)
        {    // test for inequality, in terms of equality
        return (!(_Left == _Right));
        }
    
    template<class _Ty> inline
        bool operator>(const _Ty& _Left, const _Ty& _Right)
        {    // test if _Left > _Right, in terms of operator<
        return (_Right < _Left);
        }
    
    template<class _Ty> inline
        bool operator<=(const _Ty& _Left, const _Ty& _Right)
        {    // test if _Left <= _Right, in terms of operator<
        return (!(_Right < _Left));
        }
    
    template<class _Ty> inline
        bool operator>=(const _Ty& _Left, const _Ty& _Right)
        {    // test if _Left >= _Right, in terms of operator<
        return (!(_Left < _Right));
        }
            }
    只需要定义< 和 == 就可以使用它们
     
    #include <utility>
        
    class X
    {
    public:
        bool operator==(const X& x) const;
        bool operator< (const X& x) const;
    };
    
    void foo()
    {
        using namespace std::rel_ops;
        X x1,x2;
        ...
        if(x1 != x2)
        {
        }
        ...
        if(x1 > x2)
        {
        }
    
    }
     

    2、用swap提高效率 std::swap(x,y)

    3、通过explicit,可以禁止单参数构造函数被用于自动型别转换

    4、数值极限 numeric_limits

    5、cstddef定义项

    NULL

    size_t

    ptrdiff_t  //一种带有正负号的型别,用来表示指针之间的距离

    offsetof  //表示一个成员在struct或union中的偏移量

    #define   offsetof(s,   m)   (size_t)(&(((s   *)0)->m))    

    这是offsetof的标准实现,主要是计算出结构体里成员的相对地址偏移量。    

    这里使用0只是一个使用的技巧,方便计算出偏移量。    

    根据成员的地址偏移量以及地址可以计算出宿主结构的地址:    

    成员地址   -   offset   =   宿主地址  

    #define   offsetof(s,   m)     (size_t)(&(((s   *)0)->m))    

    这个宏用来求一个结构体成员相对于这个结构体首地址的偏移量,    

    例如:    

    struct   Foo{    

      int   x;    

    };    

    这个结构体里的成员x,它的相对偏移量就是4;    

    这个宏里的0是地址,(s   *)0,这一步是把从0这个地址开始的一块大小的内存解释成这个结构体类型,&(((s   *)0)->m),这一步是取这个结构体程序m的地址,结合Foo这个结构体的例子,如果取成员x的地址,这个地址当然是4,对吧!也就是说,通过这个技巧,我们可以很方便的得到了这个成员偏移量。    

    size_t其实就是无符号整形,也就是把上面得到的那个地址转成无符号整形

    6、  容器

    序列式容器:vector, deque, list  //每个元素都有固定位置,和元素值无关

    关联式容器:set, multiset, map, multimap //有序群集,元素取决于特定的排序准则,位置取决于元素值,和插入次序无关

    7、前置式递增要比后置式递增效率高 ++pos 前置 pos++ 后置

    8、适用任何容器的程序代码

    for(pos = coll.begin(); pos != coll.end(); ++pos)  // != 最好不用 <

    9、迭代器之配接器

    1> Insert iterators 

    back_inserter, 只有提供push_back成员函数的容器中,这个函数才能使用,有vector, deque, list

    front_inserter, 只有提供push_front成员函数的容器中,这个函数才能使用,有 deque, list

    inserter, 所有STL容器都提供insert()成员函数,因此这是唯一可用于关联容器的inserter

    2> Stream iterators 

    vector<string> coll;
    copy(istream_iterator<string>(cin),
         istream_iterator<string>(),
         back_inserter(coll));
    
    unique_copy(coll.begin(), coll.end(), 
                ostream_iterator<string>(cout, "\n") );
     

    3> Revers iterators  rbegin rend

    10、容器内元素条件

    1> 必须可通过Copy构造函数进行复制,如果Copy耗费大量时间,可以通过Reference语意使用容器

    2> 必须可以通过assignment完成赋值操作

    3> 必须可以通过析构函数完成销毁动作

    4> 对序列式容器,元素的default构造函数必须可用

    5> 对于某些动作,必须定义operator==,以执行相等测试,如果有搜索需求,这一点特别重要

    6> 在关联式容器,必须定义出排序准则

    11、Map的一个Sample

    class RuntimeStringCmp
    {
    public:
        enum cmp_mode { Normal, Nocase };
    private:
        const cmp_mode mode;
    
        static bool nocase_compare(char c1, char c2)
        {
            return toupper(c1) < toupper(c2);
        }
    public:
        RuntimeStringCmp(cmp_mode m = Normal) :mode(m) {}
        bool operator() (const string& s1, const string& s2)
        {
            if( mode == Normal )
            {
                return s1 < s2;
            }
            else
            {
                return lexicographical_compare(s1.begin(), s1.end(),
                    s2.begin(), s2.end(), nocase_compare);
            }
        }
    };
    typedef map<string, string, RuntimeStringCmp> StringStringMap;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        StringStringMap col1;
        col1["a"] = "Germany";
        col1["A"] = "german";
        col1["b"] = "snag";
    
        StringStringMap ignorecase(RuntimeStringCmp::Nocase);
        ignorecase["a"] = "Germany";
        ignorecase["A"] = "german";
        ignorecase["b"] = "snag";
    
        return 0;
    }

    12、advance、distance

    advance 可将迭代器的位置增加

    distance 处理两个迭代器之间的距离

    以上两个函数对于 non-random access迭代器而言,性能并不好,应该尽量避免使用

    13、for_each、transform

    for_each接收一项操作,该操作可变动参数,因此该参数必须以by reference方式传递

    void square(int& elem);

    transform 用某操作时,该操作返回被改动后参数

    int squre(int elem);

    transform的速度稍微慢些,不过其灵活性比较高

    14、文件存取class

    fileclass

    15、操控器如何运作

    ostream& ostream::operator<< (ostream& (*op)(ostream&) )

    {

    return (*op)(*this);

    }

    使用

    std::ostream& std::endl(std::ostream& strm)

    {

    strm.put(‘\n’);

    strm.flush();

    return strm;

    }

    std::cout << std::endl;

    16、文件读取注意事项

    int _tmain(int argc, _TCHAR* argv[])
    {
        ifstream file;
        for(int i = 0; i < argc; ++i)
        {
            file.open(argv[i]);
    
            char c;
            while(file.get(c))
            {
                cout.put(c);
            }
            file.clear();  //clear eofbit and failbit set due to end-of-file
            file.close();
        }
    }
    必须调用clear(),以清除当时被设于文件尾端的状态标志,只是必要的,因为这个stream对象被多个文件共享。
    open()并不会清除任何状态标志。
    while循环可以用 std::cout<< file.rdbuf();代替
    17、Stream重定向
    std::ofstream file(“cout.txt”);
    std::cout.rdbuf(file.rdbuf());
    这两句使得写入cout的信息不被送到标准output通道,而是被送到cout.txt文件中
    1> std::fstream file("example.txt", std::ios::in | std::ios::out); //可以读写
    2> std::ofstream out("example.txt", ios::in | ios::out);
       std::istream in(out.rdbuf()); //
    3> std::filebuf buffer;
       std::ostream out(&buffer);
       std::istream in(&buffer);
       buffer.open("example.txt", std::ios::in | std::ios::out);
     
     
     
  • 相关阅读:
    工作的本质是思考
    V8、JSCore、Hermes、QuickJS,hybrid开发JS引擎怎么选
    Aspects框架的源码解读及问题解析
    饿了么移动APP的架构演进
    关键字:客户端架构演进
    以小见大,见微知著——亿万级APP架构演进之路
    理解 Swift:ObjectiveC 的构建管道
    MMKV 组件现在开源了
    进阶:iOS 性能优化系列
    你如果无法度量它,就无法管理它
  • 原文地址:https://www.cnblogs.com/wzh206/p/1698163.html
Copyright © 2011-2022 走看看