1. vector的swap(list、forward_list、deque与之类似)
#include <iostream>
#include <vector>
using namespace std;
void show(int i, vector<int> &v1, vector<int> &v2, vector<int>::iterator i1, vector<int>::iterator i2, int &r1, int &r2, int *p1, int *p2);
int main()
{
vector<int> v1(1, 1);
vector<int> v2(2, 2);
// 迭代器
auto i1 = v1.begin();
auto i2 = v2.begin();
//引用
int &r1 = *v1.begin();
int &r2 = *v2.begin();
//指针
int *p1 = &(*v1.begin());
int *p2 = &(*v2.begin());
//输出
show(0, v1, v2, i1, i2, r1, r2, p1, p2);
//交换
swap(v1, v2);
//输出
cout << "\n--------------------------------------------------" << endl;
show(1, v1, v2, i1, i2, r1, r2, p1, p2);
return 0;
}
void show(int i, vector<int> &v1, vector<int> &v2, vector<int>::iterator i1, vector<int>::iterator i2, int &r1, int &r2, int *p1, int *p2)
{
if (i)
{
cout << "vector after:\n"
<< endl;
}
else
{
cout << "vector before:\n"
<< endl;
}
cout << "v1:";
for (auto &a : v1)
{
cout << a << "(" << &a << ")\t";
}
cout << endl;
cout << "i1->" << *i1 << "(" << &(*i1) << ")"
<< "\tr1->" << r1 << "(" << &r1 << ")"
<< "\tp1->" << *p1 << "(" << &(*p1) << ")" << endl;
cout << "\nv2:";
for (auto &a : v2)
{
cout << a << "(" << &a << ")\t";
}
cout << endl;
cout << "i2->" << *i2 << "(" << &(*i2) << ")"
<< "\tr2->" << r2 << "(" << &r2 << ")"
<< "\tp2->" << *p2 << "(" << &(*p2) << ")" << endl;
}
分析:
- 迭代器i1、引用r1、指针p1始终指向0x2c0f88,其值为1,保持不变;迭代器i2、引用r2、指针p2始终指向0x2c0f98,其值为2,保持不变 。
- swap时,v1与v2交换的是其元素的地址。v1首元素地址从0x2c0f88换为0x2c0f98,v2首元素地址从0x2c0f98换为0x2c0f88。
2. array的swap
#include <iostream>
#include <array>
using namespace std;
void show(int i, array<int, 2> &a1, array<int, 2> &a2, array<int, 2>::iterator i1, array<int, 2>::iterator i2, int &r1, int &r2, int *p1, int *p2);
int main()
{
array<int, 2> a1{1, 1};
array<int, 2> a2{2, 2};
// 迭代器
auto i1 = a1.begin();
auto i2 = a2.begin();
//引用
int &r1 = *a1.begin();
int &r2 = *a2.begin();
//指针
int *p1 = &(*a1.begin());
int *p2 = &(*a2.begin());
//输出
show(0, a1, a2, i1, i2, r1, r2, p1, p2);
//交换
swap(a1, a2);
//输出
cout << "\n--------------------------------------------------" << endl;
show(1, a1, a2, i1, i2, r1, r2, p1, p2);
return 0;
}
void show(int i, array<int, 2> &a1, array<int, 2> &a2, array<int, 2>::iterator i1, array<int, 2>::iterator i2, int &r1, int &r2, int *p1, int *p2)
{
if (i)
{
cout << "array after:\n"
<< endl;
}
else
{
cout << "array before:\n"
<< endl;
}
cout << "a1:";
for (auto &a : a1)
{
cout << a << "(" << &a << ")\t";
}
cout << endl;
cout << "i1->" << *i1 << "(" << &(*i1) << ")"
<< "\tr1->" << r1 << "(" << &r1 << ")"
<< "\tp1->" << *p1 << "(" << &(*p1) << ")" << endl;
cout << "\na2:";
for (auto &a : a2)
{
cout << a << "(" << &a << ")\t";
}
cout << endl;
cout << "i2->" << *i2 << "(" << &(*i2) << ")"
<< "\tr2->" << r2 << "(" << &r2 << ")"
<< "\tp2->" << *p2 << "(" << &(*p2) << ")" << endl;
}
分析:
- 迭代器i1、引用r1、指针p1始终指向0x22feb0,但其值从1换为2;迭代器i2、引用r2、指针p2始终指向0x22fea8,但其值也从1换为2。
- swap时,a1与a2交换的是其元素的值。a1和a2首元素地址不变。
3. string的swap
#include <iostream>
#include <vector>
using namespace std;
void show(int i, string &s1, string &s2, string::iterator i1, string::iterator i2, char &r1, char &r2, char *p1, char *p2);
int main()
{
string s1 = "a";
string s2 = "bc";
// 迭代器
auto i1 = s1.begin();
auto i2 = s2.begin();
//引用
char &r1 = *s1.begin();
char &r2 = *s2.begin();
//指针
char *p1 = &(*s1.begin());
char *p2 = &(*s2.begin());
//输出
show(0, s1, s2, i1, i2, r1, r2, p1, p2);
//交换
swap(s1, s2);
//输出
cout << "\n--------------------------------------------------" << endl;
show(1, s1, s2, i1, i2, r1, r2, p1, p2);
return 0;
}
void show(int i, string &s1, string &s2, string::iterator i1, string::iterator i2, char &r1, char &r2, char *p1, char *p2)
{
if (i)
{
cout << "string after:\n"
<< endl;
}
else
{
cout << "string before:\n"
<< endl;
}
cout << "s1:";
for (auto &a : s1)
{
cout << a << "(" << &a << ")\t";
}
cout << endl;
cout << "i1->" << *i1 << "(" << &(*i1) << ")"
<< "\tr1->" << r1 << "(" << &r1 << ")"
<< "\tp1->" << *p1 << "(" << &(*p1) << ")" << endl;
cout << "\ns2:";
for (auto &a : s2)
{
cout << a << "(" << &a << ")\t";
}
cout << endl;
cout << "i2->" << *i2 << "(" << &(*i2) << ")"
<< "\tr2->" << r2 << "(" << &r2 << ")"
<< "\tp2->" << *p2 << "(" << &(*p2) << ")" << endl;
}
分析:
- string执行swap时,类似于vector,即只交换容器的内部数据结构。
- 因为string过短时,为其分配内存过于浪费,故将其存放在临时内存区域中,其元素地址与其它容器不同。string执行swap时,会将为string重新分配内存,从而造成迭代器、引用和指针失效。
4. 总结
- array执行swap时,真正交换对应的元素值;其它容器只交换其容器的内部数据结构(即元素地址)。
- array执行swap时,要求两个容器的容器类型、元素类型和元素个数相同;其它容器只要求容器类型和元素类型相同。
- string执行swap后,其指向容器元素的原迭代器、引用和指针失效;其它容器的原迭代器、引用和指针仍有效。