一、容器元素都是副本
在容器中添加元素时,系统是将元素值复制到容器里。类似地,使用一段元素初始化新容器时,新容器存放的是原始元素的副本。
被复制的原始值与新容器中的元素各不相关,此后,容器内元素值发生变化时,被复制的原值不会受到影响,反之亦然。
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); }