写在前面:
1、使用范围for遍历容器的每个元素,需要使用auto& it引用元素的同一块内存空间,不要使用auto it因为范围for的原型就是容器的迭代器遍历元素,将迭代器所指向的元素值然后拷贝给it,所以it又是栈上的一块内存空间了。建议使用引用类型,若不需要修改则写成const auto &it,需要修改写出auto &it。

2、关于array的swap的两个数组的相同类型是指容器所装的元素类型一致,还要元素的个数相同


一、swap操作交换两个相同类型的容器的内容,一般的容器(除array外),交换两个容器内容的操作会保证非常快,因为并没有交换元素本身,而只是交换了两个容器的内部数据结构。

注:这里交换两个容器的内部数据结构是指交换容器中各元素的内存地址,并不是交换各个元素变量所存储的值。除string外,swap使用之后指向容器的指针、引用和迭代器均有效(即开始指向那个元素,在swap之后这个指针、引用和迭代器依然指向该元素)。

测试代码如下:

void test1()
{
 vector<int> v1 = { 1,2,3 };
 vector<int> v2 = { 4,5,6,7,8,9 };
 auto it1 = v1.begin();
 auto it2 = v2.begin();
 cout << "交换前迭代器it1指向的元素为:" << *it1 << endl;
 cout << "交换前迭代器it2指向的元素为:" << *it2 << endl;
 cout << "交换前v1每个元素的地址和值为:";
 for (const auto &it : v1)
 {
  cout << &it << " " << it << " ";
 }
 cout << "\n交换前v2每个元素的地址和值为:";
 for (const auto &it : v2)
 {
  cout << &it << " " << it << " ";
 }
 swap(v1, v2);
 cout << endl << endl;
 cout << "交换后迭代器it1指向的元素为:" << *it1 << endl;
 cout << "交换后迭代器it2指向的元素为:" << *it2 << endl;
 cout << "交换后v1每个元素的地址和值为:";
 for (const auto &it : v1)
 {
  cout << &it << " " << it << " ";
 }
 cout << "\n交换后v2每个元素的地址和值为:";
 for (const auto &it : v2)
 {
  cout << &it << " " << it << " ";
 }
 cout << endl;
 system("pause");
 return 0;
}

运行结果如下:
在这里插入图片描述
可以看到,交换的是整个的内部数据结构,各元素(各地址)所存储的值并没有发生改变,只是这些元素(地址)已经属于不同的容器了。所以仅仅是交换了两个容器中元素的内存地址。所以swap操作后,指向容器内部的迭代器、引用和指针都任然有效,原来绑定的是哪个元素现在绑定的还是哪个元素。


二、而swap两个array则真正交换了各个元素的值:

测试代码如下:

void test2()
{
 array<int,3> a1{ 1,2,3 };
 array<int,3> a2{ 4,5,6,};
 auto it1 = a1.begin();
 auto it2 = a2.begin();
 cout << "交换前迭代器it1指向的元素为:" << *it1 << endl;
 cout << "交换前迭代器it2指向的元素为:" << *it2 << endl;
 cout << "交换前a1每个元素的地址和值为:";
 for (int i = 0; i < 3; ++i)
 {
  cout << &a1[i] << " " << a1[i] << " ";
 }
 cout << "\n交换前a2每个元素的地址和值为:";
 for (int i = 0; i < 3; ++i)
 {
  cout << &a2[i] << " " << a2[i] << " ";
 }
 swap(a1, a2);
 cout << endl << endl;
 cout << "交换后迭代器it1指向的元素为:" << *it1 << endl;
 cout << "交换后迭代器it2指向的元素为:" << *it2 << endl;
 cout << "交换后a1每个元素的地址和值为:";
 for (int i = 0; i < 3; ++i)
 {
  cout << &a1[i] << " " << a1[i] << " ";
 }
 cout << "\n交换后a2每个元素的地址和值为:";
 for (int i = 0; i < 3; ++i)
 {
  cout << &a2[i] << " " << a2[i] << " ";
 }
 }
 

运行结果如下:
在这里插入图片描述
可以看到,交换后,两个array交换了各个元素的值,即容器中所存的各个元素的内存地址并没有交换,只是交换了相应位置的元素的值,所以说swap两个array所需的时间和array中元素的数目成正比,同时,swap操作后,指向容器内部的迭代器、引用和指针都任然有效,原来绑定的是哪个元素现在绑定的还是哪个元素,只不过对应的元素值已经进行了交换。


三、和其它容器不同的是,对string调用swap会导致迭代器、引用和指针失效。因为string存储的是字符串,在string变量中真正存储字符串的是一个叫_Ptr的指针,它指向string所存储的字符串首地址,而字符串并没有固定地址,而是存储在一个临时内存区域中,所以当字符串发生改变时,会发生内存的重新分配,所以会导致迭代器、引用和指针失效。

测试代码:

void test3()
{
 string s1{ "123" };
 string s2{ "45678" };
 auto it1 = s1.begin();
 auto it2 = s2.begin();
 cout << "交换前迭代器it1指向的元素为:" << *it1 << endl;
 cout << "交换前迭代器it2指向的元素为:" << *it2 << endl;
 swap(s1, s2);
 cout << endl << endl;
 cout << "交换后迭代器it1指向的元素为:" << *it1 << endl;
 cout << "交换后迭代器it2指向的元素为:" << *it2 << endl;
}

swap之前的各变量内存窗口:
在这里插入图片描述
swap之后的发生编译错误,显示迭代器已经失效了,效果图如下:
在这里插入图片描述

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐