标准模版库学习之关联式容器
set
std::set<int> iset;
std::set<int>::iterator it = iset.insert(4).first;
(*it)++; // error. 原因:std::set的迭代器不能修改对应的元素.
//语法上不会报错,程序中也可以修改,但会破坏有序性,set可能表现出非预期的行为
这是因为:
std::set的特点是:
1. 对于插入、删除和查找操作,
2. set是一个有序的、可以前向和后向遍历的容器(双向迭代器);
3. set是一个元素类型和比较函数可以配置的容器,但是一经配置,就不可更改;
4. set的元素可以插入、删除,但是不可更改。
set在任何时刻都是一个有序的结构,而一旦破坏这个有序性,set可能表现出非预期的行为。为了保证set的概念完整性,C++STL厉
行规定了3和4两个限制,在绝大部分情况下,这两个限制是合理的。 但是,当我在set里面存的是shared_ptr元素时, 根本无所谓有没有序. 我就是要通过迭代器获取元素的非const引用. 解决如下:
#include <iostream>
#include <set>
template<class T>
inline T & GetStdSetElement(std::_Rb_tree_const_iterator<T> std_set_iterator)
{
return *(T *)&(*std_set_iterator);
}
int main()
{
using namespace std;
set<int> iset;
pair< set<int>::iterator, bool> res = iset.insert(4);
int & i = GetStdSetElement(res.first);
i++;
cout << *( iset.begin() ) << endl;
return 0;
}
/*目的:学习set容器的使用*程序输出:6 5 4 3 2 14 already exists1 2 3 4 5 61 element(s) removed3 4 6*coll2.erase(coll2.begin(), coll2.find(val));*当coll2中不存在值等于val的元素时,会返回一个指向结尾的迭代器。*此时,coll2.erase(coll2.begin(), coll2.find(val));会删除coll2中所有元素。*/#include <iostream>#include <set>using namespace std;int main(){typedef set<int, greater<int> > IntSet; //只是构造时,创建了一个从大到小排列的容器,默认为从小到大。// TEMPLATE CLASS set/*template<class _Kty,class _Pr = less<_Kty>,class _Alloc = allocator<_Kty> >class set: public _Tree<_Tset_traits<_Kty, _Pr, _Alloc, false> >:*/IntSet IntSetcoll;IntSetcoll.insert(4);IntSetcoll.insert(3);IntSetcoll.insert(5);IntSetcoll.insert(1);IntSetcoll.insert(6);IntSetcoll.insert(2);IntSetcoll.insert(5);set<int> setcoll;//默认为从小到大。setcoll.insert(4);setcoll.insert(3);setcoll.insert(5);setcoll.insert(1);setcoll.insert(6);setcoll.insert(2);setcoll.insert(5);IntSet::iterator pos;for (pos = IntSetcoll.begin(); pos != IntSetcoll.end(); ++pos){cout << *pos << ' ';}cout << endl;pair<IntSet::iterator, bool> status = IntSetcoll.insert(4);if (status.second){cout << "4 inserted as element "<< distance(IntSetcoll.begin(), status.first) + 1 << endl;}else{cout << "4 already exists" << endl;}set<int> coll2(IntSetcoll.begin(), IntSetcoll.end());copy(coll2.begin(), coll2.end(), ostream_iterator<int>(cout, " "));cout << endl;coll2.erase(coll2.begin(), coll2.find(3));int num;num = coll2.erase(5);cout << num << " element(s) removed" << endl;copy(coll2.begin(), coll2.end(), ostream_iterator<int>(cout, " "));cout << endl;getchar();}
/*目的:学习set容器的使用(二)*程序输出:coll1: 1 2 4 5 6 7coll2: 7 6 5 4 2 1coll1: 7 6 5 4 3 2 1coll1 and coll2 have same sorting criterion*RuntimeCmp(cmp_mode m = normal) : mode(m)*不能改为RuntimeCmp() : mode(normal)*带参数的构造函数,用来在程序运行中构造对象时传递参数*///print.hpp头文件#include <iostream>/* PRINT_ELEMENTS()*- print optional C-string optcstr followed by*- all elements of the collection coll*- separated by spaces*/template <class T>inline void PRINT_ELEMENTS (const T& coll, const char* optcstr = ""){typename T::const_iterator pos;std::cout << optcstr;for (pos = coll.begin(); pos != coll.end(); ++pos){std::cout << *pos << ' ';}std::cout << std::endl;}#include <iostream>#include <set>//#include "print.hpp"using namespace std;template <class T>class RuntimeCmp{public:enum cmp_mode {normal, reverse};private:cmp_mode mode;public:RuntimeCmp(cmp_mode m = normal) : mode(m){}bool operator() (const T &t1, const T &t2) const{return mode == normal ? t1 < t2 : t2 < t1;}bool operator== (const RuntimeCmp &rc){return mode == rc.mode;}};typedef set<int, RuntimeCmp<int> > IntSet; //一个类实例void fill(IntSet &set); //stl的函数声明方式int main(){IntSet coll1;fill(coll1);PRINT_ELEMENTS(coll1, "coll1: ");RuntimeCmp<int> reverse_order(RuntimeCmp<int>::reverse);IntSet coll2(reverse_order);fill(coll2);PRINT_ELEMENTS(coll2, "coll2: ");coll1 = coll2;coll1.insert(3);PRINT_ELEMENTS(coll1, "coll1: ");if (coll1.value_comp() == coll2.value_comp()){cout << "coll1 and coll2 have same sorting criterion" << endl;}else{cout << "coll1 and coll2 have different sorting criterion" << endl;}getchar();}void fill(IntSet &set){set.insert(4);set.insert(7);set.insert(5);set.insert(1);set.insert(6);set.insert(2);set.insert(5);}
map
/*目的:学习map容器的使用。本事例运用Maps、Strings并于执行期指定排序准则事例程序*程序输出:Bestatter undertakerDeutschland GermanyHaken snagHund dogUnternehmen enterprisearbeiten workdeutsch Germangehen walkunternehmen undertakearbeiten workBestatter undertakerdeutsch GermanDeutschland Germanygehen walkHaken snagHund dogUnternehmen undertake*/#include <iostream>#include <iomanip>#include <map>#include <string>#include <algorithm>using namespace std;/* function object to compare strings* - allows you to set the comparison criterion at runtime* - allows you to compare case insensitive*/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) const{if (mode == normal){return s1 < s2;} else{return lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), nocase_compare);}}};/* container type* - map with* - string keys* - string values* - the special comparison object type*/typedef map<string, string, RuntimeStringCmp> StringStringMap; //function that fills and prints such containersvoid fillAndPrint(StringStringMap &coll); //stl的函数声明方式int main(){//create a container with the default comparison criterionStringStringMap coll1;fillAndPrint(coll1);//create an objectRuntimeStringCmp ignorecase(RuntimeStringCmp::nocase);//create a containerStringStringMap coll2(ignorecase);fillAndPrint(coll2);getchar();}void fillAndPrint(StringStringMap &coll){coll["Deutschland"] = "Germany";coll["deutsch"] = "German";coll["Haken"] = "snag";coll["arbeiten"] = "work";coll["Hund"] = "dog";coll["gehen"] = "go";coll["Unternehmen"] = "enterprise";coll["unternehmen"] = "undertake";coll["gehen"] = "walk";coll["Bestatter"] = "undertaker";//printStringStringMap::iterator pos;cout.setf(ios::left, ios::adjustfield);for (pos = coll.begin(); pos != coll.end(); ++pos){cout <<setw(15) << pos->first.c_str() << " " <<pos->second << endl;}cout << endl;}