STL标准库与泛型编程(侯捷)笔记1

2024-01-08 08:04

本文主要是介绍STL标准库与泛型编程(侯捷)笔记1,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

STL标准库与泛型编程(侯捷)

本文是学习笔记,仅供个人学习使用。如有侵权,请联系删除。

参考链接

Youbute: 侯捷-STL标准库与泛型编程

B站: 侯捷 - STL

Github:STL源码剖析中源码 https://github.com/SilverMaple/STLSourceCodeNote/tree/master

Github:课程ppt和源码 https://github.com/ZachL1/Bilibili-plus

文章目录

  • STL标准库与泛型编程(侯捷)
    • 3 容器之分类与各种测试(一):array
    • 4 容器之分类与各种测试(二):vector
    • 5 容器之分类与各种测试(三)list, deque,stack, queue
    • 6 容器之分类与各种测试(四):set和unordered_set等
    • 7 分配器之测试
    • 后记

本节主要介绍STL容器的使用方法
STL有很多容器,大概分类如下:

■ 标准STL序列容器
:vector、string、deque和list。
■ 标准STL关联容器
:set、multiset、map和multimap。
■ 非标准序列容器
slist和rope。slist是一个单向链表,rope本质上是一个“重型”string。
■ 非标准的关联容器
hash_set、hash_multiset、hash_map和hash_multimap。所有hash开头的,在c++11里面改名为unordered,比如unordered_set。

3 容器之分类与各种测试(一):array

测试开50万大小的array,排序并且查找花费的时间。大概0.18秒。

const long ASIZE = 500000L;long get_a_target_long()
{
long target=0;cout << "target (0~" << RAND_MAX << "): ";cin >> target;return target;
}int compareLongs(const void* a, const void* b)
{return ( *(long*)a - *(long*)b );
}#include <array>
#include <iostream>
#include <ctime> 
#include <cstdlib> //qsort, bsearch, NULL
namespace jj01
{
void test_array()
{cout << "\ntest_array().......... \n";array<long,ASIZE> c;  	clock_t timeStart = clock();									for(long i=0; i< ASIZE; ++i) {c[i] = rand(); }cout << "milli-seconds : " << (clock()-timeStart) << endl;	//cout << "array.size()= " << c.size() << endl;		cout << "array.front()= " << c.front() << endl;	cout << "array.back()= " << c.back() << endl;	cout << "array.data()= " << c.data() << endl;	// 得到array起始地址long target = get_a_target_long();timeStart = clock();::qsort(c.data(), ASIZE, sizeof(long), compareLongs); // 前面加双冒号::表示全局函数
long* pItem = (long*)::bsearch(&target, (c.data()), ASIZE, sizeof(long), compareLongs); cout << "qsort()+bsearch(), milli-seconds : " << (clock()-timeStart) << endl;	//    if (pItem != NULL)cout << "found, " << *pItem << endl;elsecout << "not found! " << endl;	
}
}

4 容器之分类与各种测试(二):vector

测试vector:放入100万个元素到vector中,放入的时间大概是3秒。

vector当放入新元素的时候,如果空间不够,它会变成原来大小的两倍,即两倍增长。

#include <vector>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>  //snprintf()
#include <iostream>
#include <ctime> 
#include <algorithm> 	//sort()
namespace jj02
{
void test_vector(long& value)
{cout << "\ntest_vector().......... \n";vector<string> c;  	
char buf[10];clock_t timeStart = clock();								for(long i=0; i< value; ++i){try {snprintf(buf, 10, "%d", rand());c.push_back(string(buf));     		}catch(exception& p) {cout << "i=" << i << " " << p.what() << endl;	//曾經最高 i=58389486 then std::bad_allocabort();}}cout << "milli-seconds : " << (clock()-timeStart) << endl;	cout << "vector.max_size()= " << c.max_size() << endl;	//1073747823cout << "vector.size()= " << c.size() << endl;		// 真正元素的个数cout << "vector.front()= " << c.front() << endl;	cout << "vector.back()= " << c.back() << endl;	cout << "vector.data()= " << c.data() << endl;cout << "vector.capacity()= " << c.capacity() << endl << endl;	//目前vector实际分配的空间有多大	string target = get_a_target_string();{timeStart = clock();
auto pItem = find(c.begin(), c.end(), target);cout << "std::find(), milli-seconds : " << (clock()-timeStart) << endl;  if (pItem != c.end())cout << "found, " << *pItem << endl << endl;elsecout << "not found! " << endl << endl;}{timeStart = clock();sort(c.begin(), c.end());cout << "sort(), milli-seconds : " << (clock()-timeStart) << endl; timeStart = clock();	    
string* pItem = (string*)::bsearch(&target, (c.data()), c.size(), sizeof(string), compareStrings); cout << "bsearch(), milli-seconds : " << (clock()-timeStart) << endl; if (pItem != NULL)cout << "found, " << *pItem << endl << endl;elsecout << "not found! " << endl << endl;	}c.clear();test_moveable(vector<MyString>(),vector<MyStrNoMove>(), value);	
}	
}

5 容器之分类与各种测试(三)list, deque,stack, queue

使用容器list

list是双向链表,放入元素也是push_back

#include <list>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>  //snprintf()
#include <algorithm> //find()
#include <iostream>
#include <ctime> 
namespace jj03
{
void test_list(long& value)
{cout << "\ntest_list().......... \n";list<string> c;  	
char buf[10];clock_t timeStart = clock();							for(long i=0; i< value; ++i){try {snprintf(buf, 10, "%d", rand());c.push_back(string(buf));    	}catch(exception& p) {cout << "i=" << i << " " << p.what() << endl;	abort();}}cout << "milli-seconds : " << (clock()-timeStart) << endl;		cout << "list.size()= " << c.size() << endl;cout << "list.max_size()= " << c.max_size() << endl;    //357913941cout << "list.front()= " << c.front() << endl;	cout << "list.back()= " << c.back() << endl;		string target = get_a_target_string();		timeStart = clock();		
auto pItem = find(c.begin(), c.end(), target);						cout << "std::find(), milli-seconds : " << (clock()-timeStart) << endl;		if (pItem != c.end())cout << "found, " << *pItem << endl;elsecout << "not found! " << endl;	timeStart = clock();		c.sort();						cout << "c.sort(), milli-seconds : " << (clock()-timeStart) << endl;		    	c.clear();test_moveable(list<MyString>(),list<MyStrNoMove>(), value);								
}	
}

使用容器forward_list

单向链表,它没有push_back,只有push_front函数

#include <forward_list>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>  //snprintf()
#include <iostream>
#include <ctime> 
namespace jj04
{
void test_forward_list(long& value)
{cout << "\ntest_forward_list().......... \n";forward_list<string> c;  	
char buf[10];clock_t timeStart = clock();								for(long i=0; i< value; ++i){try {snprintf(buf, 10, "%d", rand());c.push_front(string(buf));  			   		}catch(exception& p) {cout << "i=" << i << " " << p.what() << endl;	abort();}}cout << "milli-seconds : " << (clock()-timeStart) << endl;	cout << "forward_list.max_size()= " << c.max_size() << endl;  //536870911cout << "forward_list.front()= " << c.front() << endl;	string target = get_a_target_string();	timeStart = clock();			
auto pItem = find(c.begin(), c.end(), target);	cout << "std::find(), milli-seconds : " << (clock()-timeStart) << endl;		if (pItem != c.end())cout << "found, " << *pItem << endl;elsecout << "not found! " << endl;	timeStart = clock();		c.sort();						cout << "c.sort(), milli-seconds : " << (clock()-timeStart) << endl;		c.clear();	 
}											 
}

使用容器slist

测试容器slist:slist也是单向链表

#include <ext\slist>	
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>  //snprintf()
#include <iostream>
#include <ctime> 
namespace jj10
{
void test_slist(long& value)
{cout << "\ntest_slist().......... \n";__gnu_cxx::slist<string> c;  	char buf[10];clock_t timeStart = clock();								for(long i=0; i< value; ++i){try {snprintf(buf, 10, "%d", rand());c.push_front(string(buf));     		}catch(exception& p) {cout << "i=" << i << " " << p.what() << endl;	abort();}}cout << "milli-seconds : " << (clock()-timeStart) << endl;			
}															
}

使用容器deque

双端队列

deque底层是分段连续,但是对使用者来说是连续的。

#include <deque>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>  //snprintf()
#include <iostream>
#include <ctime> 
namespace jj05
{
void test_deque(long& value)
{cout << "\ntest_deque().......... \n";deque<string> c;  	
char buf[10];clock_t timeStart = clock();								for(long i=0; i< value; ++i){try {snprintf(buf, 10, "%d", rand());c.push_back(string(buf));    			 		}catch(exception& p) {cout << "i=" << i << " " << p.what() << endl;	abort();}}cout << "milli-seconds : " << (clock()-timeStart) << endl;		cout << "deque.size()= " << c.size() << endl;cout << "deque.front()= " << c.front() << endl;	cout << "deque.back()= " << c.back() << endl;	cout << "deque.max_size()= " << c.max_size() << endl;	//1073741821	string target = get_a_target_string();	timeStart = clock();			
auto pItem = find(c.begin(), c.end(), target);	cout << "std::find(), milli-seconds : " << (clock()-timeStart) << endl;	if (pItem != c.end())cout << "found, " << *pItem << endl;elsecout << "not found! " << endl;	timeStart = clock();		sort(c.begin(), c.end());						cout << "sort(), milli-seconds : " << (clock()-timeStart) << endl;		c.clear();test_moveable(deque<MyString>(),deque<MyStrNoMove>(), value);		 						
}															
}

使用容器stack

stack本身使用deque实现, stack是先进后出

#include <stack>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>  //snprintf()
#include <iostream>
#include <ctime> 
namespace jj17
{
void test_stack(long& value)
{cout << "\ntest_stack().......... \n";stack<string> c;  	
char buf[10];clock_t timeStart = clock();								for(long i=0; i< value; ++i){try {snprintf(buf, 10, "%d", rand());c.push(string(buf));    			 		}catch(exception& p) {cout << "i=" << i << " " << p.what() << endl;abort();}}cout << "milli-seconds : " << (clock()-timeStart) << endl;	cout << "stack.size()= " << c.size() << endl;cout << "stack.top()= " << c.top() << endl;	c.pop();cout << "stack.size()= " << c.size() << endl;cout << "stack.top()= " << c.top() << endl;	{
stack<string, list<string>> c;		//以 list 為底層 for(long i=0; i< 10; ++i) {snprintf(buf, 10, "%d", rand());c.push(string(buf));    			 		}cout << "stack.size()= " << c.size() << endl;cout << "stack.top()= " << c.top() << endl;	c.pop();cout << "stack.size()= " << c.size() << endl;cout << "stack.top()= " << c.top() << endl;	}	{
stack<string, vector<string>> c;	//以 vector 為底層 for(long i=0; i< 10; ++i) {snprintf(buf, 10, "%d", rand());c.push(string(buf));    			 		}cout << "stack.size()= " << c.size() << endl;cout << "stack.top()= " << c.top() << endl;	c.pop();cout << "stack.size()= " << c.size() << endl;cout << "stack.top()= " << c.top() << endl;	}{
stack<string, set<string>> c;	//以 set 為底層 
/*!for(long i=0; i< 10; ++i) {snprintf(buf, 10, "%d", rand());c.push(string(buf));    			 		}cout << "stack.size()= " << c.size() << endl;cout << "stack.top()= " << c.top() << endl;	c.pop();cout << "stack.size()= " << c.size() << endl;cout << "stack.top()= " << c.top() << endl;	//[Error] 'class std::set<std::basic_string<char> >' has no member named 'push_back'
//[Error] 'class std::set<std::basic_string<char> >' has no member named 'back'
//[Error] 'class std::set<std::basic_string<char> >' has no member named 'pop_back'
*/}//!stack<string, map(string>> c5;	以 map 為底層, [Error] template argument 2 is invalid
//!stack<string>::iterator ite1;  	//[Error] 'iterator' is not a member of 'std::stack<std::basic_string<char> >'}															
}

使用容器queue

queue(队列)本身使用deque实现,queue先进先出

#include <queue>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>  //snprintf()
#include <iostream>
#include <ctime> 
namespace jj18
{
void test_queue(long& value)
{cout << "\ntest_queue().......... \n";queue<string> c;  	
char buf[10];clock_t timeStart = clock();								for(long i=0; i< value; ++i){try {snprintf(buf, 10, "%d", rand());c.push(string(buf));    			 		}catch(exception& p) {cout << "i=" << i << " " << p.what() << endl;abort();}}cout << "milli-seconds : " << (clock()-timeStart) << endl;	cout << "queue.size()= " << c.size() << endl;cout << "queue.front()= " << c.front() << endl;	cout << "queue.back()= " << c.back() << endl;		c.pop();cout << "queue.size()= " << c.size() << endl;cout << "queue.front()= " << c.front() << endl;	cout << "queue.back()= " << c.back() << endl;	{
queue<string, list<string>> c;		//以 list 為底層 for(long i=0; i< 10; ++i) {snprintf(buf, 10, "%d", rand());c.push(string(buf));    			 		}cout << "queue.size()= " << c.size() << endl;cout << "queue.front()= " << c.front() << endl;	cout << "queue.back()= " << c.back() << endl;		c.pop();cout << "queue.size()= " << c.size() << endl;cout << "queue.front()= " << c.front() << endl;	cout << "queue.back()= " << c.back() << endl;	}	{
queue<string, vector<string>> c;	//以 vector 為底層 for(long i=0; i< 10; ++i) {snprintf(buf, 10, "%d", rand());c.push(string(buf));    			 		}cout << "queue.size()= " << c.size() << endl;cout << "queue.front()= " << c.front() << endl;	cout << "queue.back()= " << c.back() << endl;		//!c.pop();  //[Error] 'class std::vector<std::basic_string<char> >' has no member named 'pop_front'cout << "queue.size()= " << c.size() << endl;cout << "queue.front()= " << c.front() << endl;	cout << "queue.back()= " << c.back() << endl;	}	{
queue<string, set<string>> c;		//以 set 為底層 
/*!for(long i=0; i< 10; ++i) {snprintf(buf, 10, "%d", rand());c.push(string(buf));    			 		}cout << "queue.size()= " << c.size() << endl;cout << "queue.front()= " << c.front() << endl;	cout << "queue.back()= " << c.back() << endl;		c.pop();cout << "queue.size()= " << c.size() << endl;cout << "queue.front()= " << c.front() << endl;	cout << "queue.back()= " << c.back() << endl;
//[Error] 'class std::set<std::basic_string<char> >' has no member named 'push_back'
//[Error] 'class std::set<std::basic_string<char> >' has no member named 'front'
//[Error] 'class std::set<std::basic_string<char> >' has no member named 'pop_front'
*/		}//! queue<string, map<string>> c5;	//以 map 為底層, [Error] template argument 2 is invalid
//! queue<string>::iterator ite1;  	//[Error] 'iterator' is not a member of 'std::queue<std::basic_string<char> >'	
}															
}

6 容器之分类与各种测试(四):set和unordered_set等

使用容器multiset

Set和multiset会根据特定的排序准则,自动将元素排序。两者不同之处在于multiset允许元素重复而set不允许。

#include <set>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>  //snprintf()
#include <iostream>
#include <ctime> 
namespace jj06
{
void test_multiset(long& value)
{cout << "\ntest_multiset().......... \n";multiset<string> c;  	
char buf[10];		
clock_t timeStart = clock();								for(long i=0; i< value; ++i){try {snprintf(buf, 10, "%d", rand());c.insert(string(buf));     				}catch(exception& p) {cout << "i=" << i << " " << p.what() << endl;	abort();}}cout << "milli-seconds : " << (clock()-timeStart) << endl;	cout << "multiset.size()= " << c.size() << endl;	cout << "multiset.max_size()= " << c.max_size() << endl;	//214748364string target = get_a_target_string();	{timeStart = clock();
auto pItem = find(c.begin(), c.end(), target);	//比 c.find(...) 慢很多	cout << "std::find(), milli-seconds : " << (clock()-timeStart) << endl;		if (pItem != c.end())cout << "found, " << *pItem << endl;elsecout << "not found! " << endl;	}{timeStart = clock();		
auto pItem = c.find(target);		//比 std::find(...) 快很多							cout << "c.find(), milli-seconds : " << (clock()-timeStart) << endl;		 if (pItem != c.end())cout << "found, " << *pItem << endl;elsecout << "not found! " << endl;	}	c.clear();test_moveable(multiset<MyString>(),multiset<MyStrNoMove>(), value);	 						
}															 
}

使用容器multimap

Map和multimap将key/value pair当作元素进行管理。它们可根据key的排序准则自动为元素排序。Multimap允许重复元素,map不允许

#include <map>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>  //snprintf()
#include <iostream>
#include <ctime> 
namespace jj07
{
void test_multimap(long& value)
{cout << "\ntest_multimap().......... \n";multimap<long, string> c;  	
char buf[10];clock_t timeStart = clock();								for(long i=0; i< value; ++i){try {snprintf(buf, 10, "%d", rand());//multimap 不可使用 [] 做 insertion c.insert(pair<long,string>(i,buf));   						}catch(exception& p) {cout << "i=" << i << " " << p.what() << endl;	abort();}}cout << "milli-seconds : " << (clock()-timeStart) << endl;	cout << "multimap.size()= " << c.size() << endl;cout << "multimap.max_size()= " << c.max_size() << endl;	//178956970	long target = get_a_target_long();		timeStart = clock();		
auto pItem = c.find(target);								cout << "c.find(), milli-seconds : " << (clock()-timeStart) << endl;	 if (pItem != c.end())cout << "found, value=" << (*pItem).second << endl;elsecout << "not found! " << endl;	  c.clear();		  					
}															 
}

使用容器unordered_multiset

不是基于红黑树,而是基于hash table。允许重复的key存在

#include <unordered_set>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>  //snprintf()
#include <iostream>
#include <ctime> 
namespace jj08
{
void test_unordered_multiset(long& value)
{cout << "\ntest_unordered_multiset().......... \n";unordered_multiset<string> c;  	
char buf[10];clock_t timeStart = clock();								for(long i=0; i< value; ++i){try {snprintf(buf, 10, "%d", rand());c.insert(string(buf));   			  		}catch(exception& p) {cout << "i=" << i << " " << p.what() << endl;	abort();}}cout << "milli-seconds : " << (clock()-timeStart) << endl;		cout << "unordered_multiset.size()= " << c.size() << endl;cout << "unordered_multiset.max_size()= " << c.max_size() << endl;	//357913941cout << "unordered_multiset.bucket_count()= " << c.bucket_count() << endl;	// 桶的数量cout << "unordered_multiset.load_factor()= " << c.load_factor() << endl;	cout << "unordered_multiset.max_load_factor()= " << c.max_load_factor() << endl;	cout << "unordered_multiset.max_bucket_count()= " << c.max_bucket_count() << endl;				for (unsigned i=0; i< 20; ++i) {cout << "bucket #" << i << " has " << c.bucket_size(i) << " elements.\n";}					string target = get_a_target_string();	{timeStart = clock();
auto pItem = find(c.begin(), c.end(), target);	//比 c.find(...) 慢很多	cout << "std::find(), milli-seconds : " << (clock()-timeStart) << endl;	if (pItem != c.end())cout << "found, " << *pItem << endl;elsecout << "not found! " << endl;	}{timeStart = clock();		
auto pItem = c.find(target);		//比 std::find(...) 快很多							cout << "c.find(), milli-seconds : " << (clock()-timeStart) << endl;	 if (pItem != c.end())cout << "found, " << *pItem << endl;elsecout << "not found! " << endl;	}		c.clear();test_moveable(unordered_multiset<MyString>(),unordered_multiset<MyStrNoMove>(), value);		 	 							
}													 

使用容器unordered_multimap

允许重复的key存在

#include <unordered_map>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>  //snprintf()
#include <iostream>
#include <ctime> 
namespace jj09
{
void test_unordered_multimap(long& value)
{cout << "\ntest_unordered_multimap().......... \n";unordered_multimap<long, string> c;  	
char buf[10];clock_t timeStart = clock();								for(long i=0; i< value; ++i){try {snprintf(buf, 10, "%d", rand());//multimap 不可使用 [] 進行 insertion c.insert(pair<long,string>(i,buf));}catch(exception& p) {cout << "i=" << i << " " << p.what() << endl;	abort();}}cout << "milli-seconds : " << (clock()-timeStart) << endl;		cout << "unordered_multimap.size()= " << c.size() << endl;	cout << "unordered_multimap.max_size()= " << c.max_size() << endl;	//357913941	long target = get_a_target_long();		timeStart = clock();		
auto pItem = c.find(target);								cout << "c.find(), milli-seconds : " << (clock()-timeStart) << endl;		 if (pItem != c.end())cout << "found, value=" << (*pItem).second << endl;elsecout << "not found! " << endl;		
}															 
}

使用容器set

set中key不可重复

#include <set>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>  //snprintf()
#include <iostream>
#include <ctime> 
namespace jj13
{
void test_set(long& value)
{cout << "\ntest_set().......... \n";set<string> c;  	
char buf[10];clock_t timeStart = clock();								for(long i=0; i< value; ++i){try {snprintf(buf, 10, "%d", rand());c.insert(string(buf));     					}catch(exception& p) {cout << "i=" << i << " " << p.what() << endl;	abort();}}cout << "milli-seconds : " << (clock()-timeStart) << endl;		cout << "set.size()= " << c.size() << endl;cout << "set.max_size()= " << c.max_size() << endl;	   //214748364string target = get_a_target_string();	{timeStart = clock();
auto pItem = find(c.begin(), c.end(), target);	//比 c.find(...) 慢很多	cout << "std::find(), milli-seconds : " << (clock()-timeStart) << endl;		if (pItem != c.end())cout << "found, " << *pItem << endl;elsecout << "not found! " << endl;	}{timeStart = clock();		
auto pItem = c.find(target);		//比 std::find(...) 快很多							cout << "c.find(), milli-seconds : " << (clock()-timeStart) << endl;		 if (pItem != c.end())cout << "found, " << *pItem << endl;elsecout << "not found! " << endl;	}							
}															 
}

使用容器map

底部是红黑树,存的元素是不能重复的

#include <map>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>  //snprintf()
#include <iostream>
#include <ctime> 
namespace jj14
{
void test_map(long& value)
{cout << "\ntest_map().......... \n";map<long, string> c;  	
char buf[10];clock_t timeStart = clock();								for(long i=0; i< value; ++i){try {snprintf(buf, 10, "%d", rand());c[i] = string(buf);  					}catch(exception& p) {cout << "i=" << i << " " << p.what() << endl;	abort();}}cout << "milli-seconds : " << (clock()-timeStart) << endl;	cout << "map.size()= " << c.size() << endl;	cout << "map.max_size()= " << c.max_size() << endl;		//178956970long target = get_a_target_long();		timeStart = clock();		
auto pItem = c.find(target);								cout << "c.find(), milli-seconds : " << (clock()-timeStart) << endl;		 if (pItem != c.end())cout << "found, value=" << (*pItem).second << endl;elsecout << "not found! " << endl;			c.clear();					
}															 
}

使用容器 unordered_set

底层实现是hash table.

#include <unordered_set>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>  //snprintf()
#include <iostream>
#include <ctime> 
namespace jj15
{
void test_unordered_set(long& value)
{cout << "\ntest_unordered_set().......... \n";unordered_set<string> c;  	
char buf[10];clock_t timeStart = clock();								for(long i=0; i< value; ++i){try {snprintf(buf, 10, "%d", rand());c.insert(string(buf));    			 		}catch(exception& p) {cout << "i=" << i << " " << p.what() << endl;	abort();}}cout << "milli-seconds : " << (clock()-timeStart) << endl;		cout << "unordered_set.size()= " << c.size() << endl;	cout << "unordered_set.max_size()= " << c.max_size() << endl;  //357913941cout << "unordered_set.bucket_count()= " << c.bucket_count() << endl;	cout << "unordered_set.load_factor()= " << c.load_factor() << endl;	cout << "unordered_set.max_load_factor()= " << c.max_load_factor() << endl;	cout << "unordered_set.max_bucket_count()= " << c.max_bucket_count() << endl;			for (unsigned i=0; i< 20; ++i) {cout << "bucket #" << i << " has " << c.bucket_size(i) << " elements.\n";}			string target = get_a_target_string();	{timeStart = clock();
auto pItem = find(c.begin(), c.end(), target);	//比 c.find(...) 慢很多	cout << "std::find(), milli-seconds : " << (clock()-timeStart) << endl;		if (pItem != c.end())cout << "found, " << *pItem << endl;elsecout << "not found! " << endl;	}{timeStart = clock();		
auto pItem = c.find(target);		//比 std::find(...) 快很多							cout << "c.find(), milli-seconds : " << (clock()-timeStart) << endl;		 if (pItem != c.end())cout << "found, " << *pItem << endl;elsecout << "not found! " << endl;	}	
}															 
}

使用容器unordered_map

底层实现是hash table。

#include <unordered_map>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>  //snprintf()
#include <iostream>
#include <ctime> 
namespace jj16
{
void test_unordered_map(long& value)
{cout << "\ntest_unordered_map().......... \n";unordered_map<long, string> c;  	
char buf[10];clock_t timeStart = clock();								for(long i=0; i< value; ++i){try {snprintf(buf, 10, "%d", rand());c[i] = string(buf);  		}catch(exception& p) {cout << "i=" << i << " " << p.what() << endl;	abort();}}cout << "milli-seconds : " << (clock()-timeStart) << endl;		cout << "unordered_map.size()= " << c.size() << endl;	//357913941cout << "unordered_map.max_size()= " << c.max_size() << endl;	long target = get_a_target_long();		timeStart = clock();	
//! auto pItem = find(c.begin(), c.end(), target);	//map 不適用 std::find() 			
auto pItem = c.find(target);cout << "c.find(), milli-seconds : " << (clock()-timeStart) << endl;		 if (pItem != c.end())cout << "found, value=" << (*pItem).second << endl;elsecout << "not found! " << endl;		
}															 
}

7 分配器之测试

使用容器的时候,如果没有显式指定分配器,会使用默认的分配器。

在这里插入图片描述

#include <list>
#include <stdexcept>
#include <string>
#include <cstdlib> 		//abort()
#include <cstdio>  		//snprintf()
#include <algorithm> 	//find()
#include <iostream>
#include <ctime> #include <cstddef>
#include <memory>	//內含 std::allocator  //欲使用 std::allocator 以外的 allocator, 得自行 #include <ext\...> 
#ifdef __GNUC__		
#include <ext\array_allocator.h>
#include <ext\mt_allocator.h>
#include <ext\debug_allocator.h>
#include <ext\pool_allocator.h>
#include <ext\bitmap_allocator.h>
#include <ext\malloc_allocator.h>
#include <ext\new_allocator.h>  
#endifnamespace jj20
{
//pass A object to function template impl(),
//而 A 本身是個 class template, 帶有 type parameter T,  
//那麼有無可能在 impl() 中抓出 T, 創建一個 list<T, A<T>> object? 
//以下先暫時迴避上述疑問.void test_list_with_special_allocator()
{
#ifdef __GNUC__	cout << "\ntest_list_with_special_allocator().......... \n";//不能在 switch case 中宣告,只好下面這樣. 				//1000000次 list<string, allocator<string>> c1;						//3140list<string, __gnu_cxx::malloc_allocator<string>> c2;  	//3110list<string, __gnu_cxx::new_allocator<string>> c3; 		//3156list<string, __gnu_cxx::__pool_alloc<string>> c4;  		//4922list<string, __gnu_cxx::__mt_alloc<string>> c5; 		//3297list<string, __gnu_cxx::bitmap_allocator<string>> c6;  	//4781 														int choice;
long value;     cout << "select: "<< " (1) std::allocator "<< " (2) malloc_allocator "<< " (3) new_allocator "<< " (4) __pool_alloc "<< " (5) __mt_alloc "<< " (6) bitmap_allocator ";cin >> choice;if ( choice != 0 ) {cout << "how many elements: ";cin >> value; 		}char buf[10];			
clock_t timeStart = clock();								for(long i=0; i< value; ++i){try {snprintf(buf, 10, "%d", i);switch (choice) {case 1 : 	c1.push_back(string(buf)); 	break;case 2 : 	c2.push_back(string(buf)); 	break;		case 3 : 	c3.push_back(string(buf)); break;		case 4 : 	c4.push_back(string(buf)); 	break;		case 5 : 	c5.push_back(string(buf)); 		break;		case 6 : 	c6.push_back(string(buf)); 	break;				default: break;		}    		   		}catch(exception& p) {cout << "i=" << i << " " << p.what() << endl;	abort();}}cout << "a lot of push_back(), milli-seconds : " << (clock()-timeStart) << endl;	//test all allocators' allocate() & deallocate();int* p; 	allocator<int> alloc1;	p = alloc1.allocate(1);  alloc1.deallocate(p,1); 	__gnu_cxx::malloc_allocator<int> alloc2;  p = alloc2.allocate(1);  alloc2.deallocate(p,1);  	__gnu_cxx::new_allocator<int> alloc3; 	p = alloc3.allocate(1);  alloc3.deallocate(p,1); 	__gnu_cxx::__pool_alloc<int> alloc4;  	p = alloc4.allocate(2);  alloc4.deallocate(p,2); 	//我刻意令參數為 2, 但這有何意義!! 一次要 2 個 ints? __gnu_cxx::__mt_alloc<int> alloc5; 	p = alloc5.allocate(1);  alloc5.deallocate(p,1);  	__gnu_cxx::bitmap_allocator<int> alloc6;  	p = alloc6.allocate(3);  alloc6.deallocate(p,3);  	//我刻意令參數為 3, 但這有何意義!! 一次要 3 個 ints? 
#endif 			
}															
}

后记

这是STL标准库与泛型编程(侯捷)的第一份笔记,后续笔记会陆续更新。

这篇关于STL标准库与泛型编程(侯捷)笔记1的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/582807

相关文章

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

利用Python快速搭建Markdown笔记发布系统

《利用Python快速搭建Markdown笔记发布系统》这篇文章主要为大家详细介绍了使用Python生态的成熟工具,在30分钟内搭建一个支持Markdown渲染、分类标签、全文搜索的私有化知识发布系统... 目录引言:为什么要自建知识博客一、技术选型:极简主义开发栈二、系统架构设计三、核心代码实现(分步解析

Go标准库常见错误分析和解决办法

《Go标准库常见错误分析和解决办法》Go语言的标准库为开发者提供了丰富且高效的工具,涵盖了从网络编程到文件操作等各个方面,然而,标准库虽好,使用不当却可能适得其反,正所谓工欲善其事,必先利其器,本文将... 目录1. 使用了错误的time.Duration2. time.After导致的内存泄漏3. jsO

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制

C++ Primer 标准库vector示例详解

《C++Primer标准库vector示例详解》该文章主要介绍了C++标准库中的vector类型,包括其定义、初始化、成员函数以及常见操作,文章详细解释了如何使用vector来存储和操作对象集合,... 目录3.3标准库Vector定义和初始化vector对象通列表初始化vector对象创建指定数量的元素值

Go语言利用泛型封装常见的Map操作

《Go语言利用泛型封装常见的Map操作》Go语言在1.18版本中引入了泛型,这是Go语言发展的一个重要里程碑,它极大地增强了语言的表达能力和灵活性,本文将通过泛型实现封装常见的Map操作,感... 目录什么是泛型泛型解决了什么问题Go泛型基于泛型的常见Map操作代码合集总结什么是泛型泛型是一种编程范式,允

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同

PyCharm接入DeepSeek实现AI编程的操作流程

《PyCharm接入DeepSeek实现AI编程的操作流程》DeepSeek是一家专注于人工智能技术研发的公司,致力于开发高性能、低成本的AI模型,接下来,我们把DeepSeek接入到PyCharm中... 目录引言效果演示创建API key在PyCharm中下载Continue插件配置Continue引言