一、容器元素都是副本
在容器中添加元素時,系統是将元素值複制到容器裡。類似地,使用一段元素初始化新容器時,新容器存放的是原始元素的副本。
被複制的原始值與新容器中的元素各不相關,此後,容器内元素值發生變化時,被複制的原值不會受到影響,反之亦然。
void test_copy() { int i = 10; std::vector<int> vec; vec.push_back(i); *(vec.begin()) = 9; std::cout << *(vec.begin()) << std::endl; //9 std::cout << i << std::endl; //10,放進容器的值是副本,對容器的元素進行修改不影響原來的對象 }
二、任何對容器的增删操作都可能對已經定義的疊代器失效
void test_iterator() { std::list<int> ls; ls.push_front(1); std::list<int>::iterator begin = ls.begin(); std::cout << *begin << std::endl; //1 ls.push_front(2); // 對于push_front操作隻适合list和deque容器 std::cout << *begin << std::endl; //1,begin依然指向原來的元素,并沒有指向新添加的元素2 begin = ls.begin(); // std::cout << *begin << std::endl; //2 }
三、測試insert操作
void printDeque( std::deque<int>::iterator &begin, std::deque<int>::iterator &end ) { while( begin != end ) { std::cout << *begin << "_"; ++begin; } std::cout << std::endl; } // 測試insert操作 void test_insert() { std::deque<int> de; for( unsigned int index = 0; index != 5; ++index ) { de.push_front(index); } // 逆序疊代器 std::deque<int>::reverse_iterator rit = de.rbegin(); // 指向容器的最後一位 while( rit != de.rend() ) // 容器第一位的前一位 { std::cout << *rit << std::endl; ++rit; } std::deque<int>::iterator it; it = de.begin(); ++it; // 在指定的疊代器前面插入對象的副本 de.insert(it,10); std::deque<int>::iterator begin = de.begin(), end = de.end(); printDeque(begin, end); // 4_10_3_2_1_0_ // 在指定的疊代器前面連續插入n個對象的副本 de.insert(it,3,20); std::deque<int>::iterator begin2 = de.begin(), end2 = de.end(); printDeque(begin2,end2);// 4_10_20_20_20_3_2_1_0_ } // 插入兩個疊代器标記範圍内的元素 void test_insert_2() { std::deque<int> de; for( unsigned int index = 0; index != 5; ++index ) { de.push_front(index); } int arr[] = { 10, 11, 12, 13, 14, 15}; de.insert(de.begin(), arr, arr+sizeof(arr)/sizeof(int)/2); std::deque<int>::iterator begin = de.begin(), end = de.end(); printDeque(begin, end); // 10_11_12_4_3_2_1_0_ } int main() { test_insert_2(); return 0; }
四、放進容器的是對象的副本,取出容器的是對象的引用
// 從容器中傳回引用的方法:front()、back()、begin()、end()、at【隻對vec和deque有效】等 void test_inout() { int i = 10; std::vector<int> vec; vec.push_back(i); i = 100; std::cout << i << std::endl; // 100 std::cout << vec.front() << std::endl; // 10,修改i的值并沒有改變容器中的副本 // 傳回的是引用,修改j的值等同于修改容器中對象,如果将j定義為:int j = vec.front(), // 則對j的修改不會對容器的對象起作用 int &j = vec.front(); j = 1000; std::cout << i << std::endl; // 100 std::cout << j << std::endl; // 1000 std::cout << vec.front() << std::endl; // 1000, }
五、關于resize操作
resize 操作可能會使疊代器失效。在 vector 或 deque 容器上做 resize 操作有可能會使其所有的疊代器都失效。
對于所有的容器類型,如果 resize 操作壓縮了容器,則指向已删除的元素疊代器失效。
/* c.resize(n): 調整容器 c 的長度大小,使其能容納 n 個元素,如果 n < c.size(),則删除多出來的元素;否則,添加采用值初始化的新元素 c.resize(n,t): 調整容器 c 的長度大小,使其能容納 n 個元素。所有新添加的元素值都為 t */ void test_size_resize() { std::vector<std::string> vec; if(vec.empty()) { std::cout << vec.size() << std::endl; } std::cout << "容器能容納的最多元素個數為:" << vec.max_size() << std::endl; // 1073741823 vec.push_back("111"); std::cout << vec.size() << std::endl; // 1 vec.resize(10); std::cout << "resize(10): " << vec.size() << std::endl; // 10 vec.resize(3, "aaa"); std::cout << "resize(3): " << vec.size() << std::endl; // 3 for( unsigned int i = 0; i != vec.size(); ++i ) { // 0:111 1: 2: // resize(n,t):隻有n大于原來的容器的容量時,新添加的元素才會初始化為t // 否則調用就調用resize(n)方法 std::cout << i << ":" << vec[i] << std::endl; } vec.push_back("222"); vec.push_back("333"); std::cout << vec.size() << std::endl; // 4 }
六、begin/end/front/back/at
// 如果容器為空或容器的大小為1,則front和back操作傳回的對象相等 void test_front_back() { std::list<int> ls; int front = ls.front(), back = ls.back(); if( front == back ) { // 調用空容器的 front 或 back 函數,通常都會導緻程式出現嚴重的錯誤 std::cout << "front element equals back element" << std::endl; // ok } ls.push_back(1); front = ls.front(); back = ls.back(); if( front == back ) { std::cout << "front element equals back element" << std::endl; // ok } } /* 在這段程式中,有兩個地方值得注意: 1、end 疊代器指向容器的超出末端的下一位置,是以必須先對其減 1 才能擷取最後一個元素; 2、在調用 front 或 back 函數之前,或者在對 begin 或end 傳回的疊代器進行解引用運算之前,必須保證ls容器非空, 如果該list 容器為空,則 if 語句内所有的操作都沒有定義。 */ void test_front_back_begin_end( std::list<int> &ls ) { if( !ls.empty() ) { std::list<int>::reference begin = *ls.begin(); std::list<int>::reference front = ls.front(); if( begin == front ) { std::cout << "ok" << std::endl; // ok } std::list<int>::reference end = *--ls.end(); std::list<int>::reference back = ls.back(); if( end == back ) { std::cout << "ok" << std::endl; // ok } } } // 使用下标操作的兩種方式僅隻适合vector和deque,并不适合list // 但是如果給出的下标無效,at 函數将會抛出 out_of_range異常 void test_at() { std::vector<std::string> svec; std::cout << svec[0]; std::cout << svec.at(0); }