现在的位置: 首页 > 综合 > 正文

STL笔记

2013年12月22日 ⁄ 综合 ⁄ 共 6254字 ⁄ 字号 评论关闭
STL组件

1.打印容器内的所有元素

std::copy(vi1.begin(),vi1.end(), std::ostream_iterator<int>(std::cout, ", "));
2.sort排序
struct comp
{
    bool operator()(int x, int y) const // 由大到小
        {
            return x>y;
        }
};
std::sort(vi1.begin(), vi1.end(), comp());
3.find、find_if
find成功返回指向查找到的元素的位置,失败返回end();容器区间[     ), 左边闭区间右边开区间
    std::vector<int>::iterator iter = std::find(vi1.begin(), vi1.end(), 9);
    if (iter == vi1.end())
    {
        std::cout << "fail" << std::endl;
    }
    else
    {
        std::cout << "success" << std::endl;
    }
find_if如果容器中的元素可以让pred返回值为真则找到了,否则没有找到
bool pred(int x)
{
    return (x % 3 == 0);
}
std::vector<int>::iterator iter = std::find_if(vi1.begin(), vi1.end(), pred);
4.stack
push, pop, top, size, empty
初始化,默认用deque
    std::deque<int> que(5, 200);
    const int xx[] = {3, 56, 45, 234};
    const int len = sizeof(xx) / sizeof(xx[0]);
    std::vector<int> vec(xx, xx+len);
    std::stack<int> sta1(que);
    std::stack<int, std::vector<int> > sta2(vec);
    std::cout << sta1.top() << std::endl;
5.equal
通常处理这种有多个区间的算法,你必须设定第一个区间的起点和终点,至于至于其它区间,你只需设定起点即可,终点是由第一区间的元素数量推导出来的。所以要注意两个区间的实际元素个数!
    int x[5] = {3, 5, 2, 5, 3};
    int y[5] = {3, 5, 2, 4, 3};
    std::vector<int> vi1(x, x+5);
    std::vector<int> vi2(y, y+5);
    bool isEqual = std::equal(vi1.begin(), vi1.end(), vi2.begin());
6.迭代器
Insert iterators(安插型迭代器)
    它可以解决算法的“目标空间不足”问题,它可以促使目标区间的大小按需要成长;
Stream iterators(流迭代器)
Reverse Iterators(逆向迭代器)
7.remove
注意remove后容器中的元素个数是不变的
    int num[6] = {3, 5, 56, 2, 5, 1};
    vector<int> coll(num, num+6);
    copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
    cout << endl;
    vector<int>::iterator reEnd = remove(coll.begin(), coll.end(), 5);
    coll.erase(reEnd, coll.end()); // !!!
    copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
    cout << endl;
或者合成一条语句:
    coll.erase(remove(coll.begin(), coll.end(), 5), coll.end());
8.set
struct Greater
{
    bool operator()(const int &x, const int &y) const
    {
        return x > y;
    }
};
int main(void)
{
    int xx[] = {43, 54, 2, 6, 34};
    const int num = sizeof(xx) / sizeof(xx[0]);
    
    std::cout << "小到大" << std::endl;
    typedef std::set<int> IntSet;
    IntSet intSet(xx, xx+num);
    std::copy(intSet.begin(), intSet.end(), std::ostream_iterator<int>(cout, "\n"));
    
    std::cout << "大到小" << std::endl;
    typedef std::set<int, Greater > IntSet2;
    IntSet2 intSet2(xx, xx+num);
    std::copy(intSet2.begin(), intSet2.end(), std::ostream_iterator<int>(cout, "\n"));
        
    system("pause");
}
9.multimap
void PrintMap(std::pair<int, std::string> pr)
{
    std::cout << pr.first << ", " << pr.second << std::endl;
}
int main(void)
{    
    typedef std::multimap<int, std::string> IntStrMap;
    IntStrMap intStrMap;
    intStrMap.insert(make_pair(3, "third"));
    intStrMap.insert(make_pair(2, "second"));
    intStrMap.insert(make_pair(4, "fourth"));
    
    for_each(intStrMap.begin(), intStrMap.end(), PrintMap);
    
    system("pause");
}

10.ostream_iterator自定义输出,在类型里面重载不行?
typedef struct
{
int x, y;
}T;
std::ostream& operator<<(std::ostream &os, const T &t)
{
os << t.x << ", " << t.y;
return os;
}
int _tmain(int argc, _TCHAR* argv[])
{
T x[3] = {{1, 2}, {3, 4}, {5, 6}};
std::vector<T> vec(x, x+3);
std::copy(vec.begin(), vec.end(), std::ostream_iterator<T>(std::cout, "\n"));
system("pause");
return 0;
}
11.自定义泛型函数
template<class T>
inline void PrintElems(const T &coll, const char *str = "")
{
    typename T::const_iterator pos;
    std::cout << str;
    for (pos=coll.begin(); pos!=coll.end(); ++pos)
    {
        std::cout << *pos << ' ';
    }
    std::cout << std::endl;
}
其中pos被声明为“传入之容器型别”内的迭代器型别,关键词typename在此不可或缺,用以表明const_iterator是型别T所定义的一个型别,而不是一个型别为T的值(类似如类里面的某个public成员值)。
12. for_each
void print(int elem)
{
    std::cout << elem << ' ';
}
int main()
{
    int arr[5] = {1, 4, 6, 3, 2};
    std::vector<int> coll(arr, arr+5);
    std::for_each(coll.begin(),coll.end(), print);
    return 0;
}
13.仿函数,行为类似如函数的对象
class AddValue
{
public:
    AddValue(int value)
        : _value(value)
        {
        }
    
    void operator()(int &elem) const
        {
            elem += _value;
        }
private:
    int _value;
};
int main()
{
    int arr[5] = {1, 4, 6, 3, 2};
    std::vector<int> coll(arr, arr+5);
    std::copy(coll.begin(), coll.end(), std::ostream_iterator<int>(std::cout, " "));
    std::cout << std::endl;
    AddValue addten(10);
    AddValue addone(1);
    std::for_each(coll.begin(), coll.end(), AddValue(100));
    std::copy(coll.begin(), coll.end(), std::ostream_iterator<int>(std::cout, " "));
    
    return 0;
}
14.容器元素的条件:必须能进行copy构造、assignment操作符、析构函数
序列式容器元素的default构造函数必须可用;
对于某些动作,必须定义operator==以执行相等测试。如果你有搜寻需求这一点特别重要;
在关联式容器中,元素必须定义出排序准则。缺省情况下是operator<,透过仿函数less<>被调用;
千万不要将auto_ptr当做容器元素;
15.vector 动态数组
    支持随机存取,可以在常数时间内存取任何一个元素,在末端附加或删除元素时性能相当好,可是如果在前端或者中端安插或删除元素,性能就不怎么样了,因为操作点之后的每一个元素都必须移到另一位置,而每一次移动都得调用assignment操作符。
    capacity()函数会返回vector实际能够容纳的元素数量,如果超过这个数量,vector就有必要重新配置内部存储器,这里会造成两个问题:一旦内存重新配置,和vector元素相关的所有references、pointer、iterators都会失效(???);内存重新配置很耗时间。
    所以如果vector中的元素是references、pointer、iterators一定要注意内存重新配置的问题。你可以用reserver()保留适当容量,避免一再重新配置内存,当然这个操作也是很费时间的。
    swap()方法也会带来references、pointer、iterators失效。
16.deque 双端队列
    内部结构类似如vector,只是在两端插入、删除元素很快。
17.list 双向链表
    不支持随机存取,遍历元素缓慢;安插、移除元素很快,可以在常数时间内完成。安插和删除动作并不会造成指向其他元素的各个pointers、references、iterators失效;
    list对于异常的处理方式是:要么操作成功,要么什么都不发生;
18.set和multiset,通常有平衡二叉树完成
    会根据特定的排序准则,自动将元素排序,两者不同处在于multiset允许元素重复而set不允许。
    由于自动排序所以你不能直接改变元素值,因为这样会打乱原本正确的顺序。因此,要改变元素值,必须先删除旧元素,再插入新元素。
    注意排序准则是型别的一部分,在要求型别一致的地方,即要求排序准则也要一致。
19.map和multimap,通常以平衡二叉树完成,将key/value pair(键值对)当做元素
    根据元素key自动对元素进行排序,用key来搜寻某个元素时有很好的性能,用value则性能很糟糕。你不可以直接改变元素的key,但可以改变value,如果要修改一个key,必须要移除该key的元素,然后再插入新的key/value元素。
20.类似如shared_ptr智能指针
#include <iostream>
#include <cstdlib>
#include <cstring>
template<class T>
class CountedPtr
{
public:
    explicit CountedPtr(T *p = 0)
        : _ptr(p), _count(new long(1))
        {
        }
    ~CountedPtr()
        {
            dispose();
        }
    
    CountedPtr(const CountedPtr<T> &p)
        : _ptr(p._ptr), _count(p._count)
        {
            ++*_count;
        }
    CountedPtr<T>& operator=(const CountedPtr<T> &p)
        {
            if (this != &p)
            {
                dispose();
                _ptr = p._ptr;
                _count = p._count;
                ++*_count;
            }
            return *this;
        }
    T& operator*() const
        {
            return *_ptr;
        }
    T* operator->() const
        {
            return _ptr;
        }
private:
    void dispose()
        {
            if (--*_count == 0)
            {
                delete _count;
                delete _ptr;
            }
        }
private:
    T *_ptr;
    long *_count;
};
int main(void)
{
    CountedPtr<char> p(new char);
    CountedPtr<char> p2(p);
    *p2 = 'A';
    
    std::cout <<  *p << std::endl;
}
21 std::map查找的时候不区分大小写

// 不区分大小写
struct nocase_less : public std::binary_function<std::string, std::string, bool>
{
    bool operator() (const std::string& left,  const std::string& right) const
    {
        return _stricmp(left.c_str(), right.c_str()) < 0;
    }
};

typedef string RowKey;
typedef map<RowKey, RowValue, nocase_less> CodeFileContent;    // 每行的相对路径作为key,其他作为value

【上篇】
【下篇】

抱歉!评论已关闭.