文章标题 原创 翻译 转载 文章内容 STL组件 # 打印容器内的所有元素 ``` std::copy(vi1.begin(),vi1.end(), std::ostream_iterator<int>(std::cout, ", ")); ``` # sort排序 ``` struct comp { bool operator()(int x, int y) const // 由大到小 { return x>y; } }; std::sort(vi1.begin(), vi1.end(), comp()); ``` # 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); ``` # 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; ``` # 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()); ``` # 迭代器 Insert iterators(安插型迭代器) 它可以解决算法的“目标空间不足”问题,它可以促使目标区间的大小按需要成长; Stream iterators(流迭代器) Reverse Iterators(逆向迭代器) # 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()); ``` # 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"); } ``` # 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"); } ``` # 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; } ``` # 自定义泛型函数 ``` 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成员值)。 # 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; } ``` # 仿函数,行为类似如函数的对象 ``` 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; } ``` # 容器元素的条件:必须能进行copy构造、assignment操作符、析构函数 序列式容器元素的default构造函数必须可用; 对于某些动作,必须定义operator==以执行相等测试。如果你有搜寻需求这一点特别重要; 在关联式容器中,元素必须定义出排序准则。缺省情况下是operator<,透过仿函数less<>被调用; 千万不要将auto_ptr当做容器元素; # vector 动态数组 支持随机存取,可以在常数时间内存取任何一个元素,在末端附加或删除元素时性能相当好,可是如果在前端或者中端安插或删除元素,性能就不怎么样了,因为操作点之后的每一个元素都必须移到另一位置,而每一次移动都得调用assignment操作符。 capacity()函数会返回vector实际能够容纳的元素数量,如果超过这个数量,vector就有必要重新配置内部存储器,这里会造成两个问题:一旦内存重新配置,和vector元素相关的所有references、pointer、iterators都会失效(???);内存重新配置很耗时间。 所以如果vector中的元素是references、pointer、iterators一定要注意内存重新配置的问题。你可以用reserver()保留适当容量,避免一再重新配置内存,当然这个操作也是很费时间的。 swap()方法也会带来references、pointer、iterators失效。 # deque 双端队列 内部结构类似如vector,只是在两端插入、删除元素很快。 # list 双向链表 不支持随机存取,遍历元素缓慢;安插、移除元素很快,可以在常数时间内完成。安插和删除动作并不会造成指向其他元素的各个pointers、references、iterators失效; list对于异常的处理方式是:要么操作成功,要么什么都不发生; # set和multiset,通常有平衡二叉树完成 会根据特定的排序准则,自动将元素排序,两者不同处在于multiset允许元素重复而set不允许。 由于自动排序所以你不能直接改变元素值,因为这样会打乱原本正确的顺序。因此,要改变元素值,必须先删除旧元素,再插入新元素。 注意排序准则是型别的一部分,在要求型别一致的地方,即要求排序准则也要一致。 # map和multimap,通常以平衡二叉树完成,将key/value pair(键值对)当做元素 根据元素key自动对元素进行排序,用key来搜寻某个元素时有很好的性能,用value则性能很糟糕。你不可以直接改变元素的key,但可以改变value,如果要修改一个key,必须要移除该key的元素,然后再插入新的key/value元素。 # 类似如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; } ``` # 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 ``` 文章类别 Python Mobile Android Java Shell Life Database Bug Windows IOS Tools Boost Node.js Mac Product Tips C/C++ Golang Javascript React Qt MQ MongoDB Design Web Linux LLM ChatGPT RAG AI 提交