在C++ Primer 9.2.5中讲道:
与其他容器不同,swap两个array会真正交换他们的元素。因此,交换两个array所需的时间与array中元素的数目成正比。
因此,对于array,在swap操作之后,指针、引用和迭代器所绑定的元素保持不变,但元素值已经与另一个array中对应元素值进行了交换。
说明交换操作并不改变元素的内存地址,只是将两个数组相同索引所对应的内存中的值进行交换。写测试程序验证一下:
#include
#include
int main() {
std::array ai1= {1, 2, 3,
4, 5, 6,
7, 8, 9,
0};
std::array ai2= {11, 12, 13,
14, 15, 16,
17, 18, 19,
10};
for(const auto& i : ai1){
std::cout << &i << " ";
}
std::cout << std::endl;
for(const auto& i : ai2){
std::cout << &i << " ";
}
std::cout << std::endl;
using std::swap;
swap(ai1, ai2);
std::cout << "after swap :\n";
for(const auto& i : ai1){
std::cout << &i << " ";
}
std::cout << std::endl;
for(const auto& i : ai2){
std::cout << &i << " ";
}
std::cout << std::endl;
std::cout << "value:" << std::endl;
for(const auto& i : ai1){
std::cout << i << " ";
}
std::cout << std::endl;
for(const auto& i : ai2){
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
输出:
0x7ffe7f5a6c60 0x7ffe7f5a6c64 0x7ffe7f5a6c68 0x7ffe7f5a6c6c 0x7ffe7f5a6c70 0x7ffe7f5a6c74 0x7ffe7f5a6c78 0x7ffe7f5a6c7c 0x7ffe7f5a6c80 0x7ffe7f5a6c84
0x7ffe7f5a6c90 0x7ffe7f5a6c94 0x7ffe7f5a6c98 0x7ffe7f5a6c9c 0x7ffe7f5a6ca0 0x7ffe7f5a6ca4 0x7ffe7f5a6ca8 0x7ffe7f5a6cac 0x7ffe7f5a6cb0 0x7ffe7f5a6cb4
after swap :
0x7ffe7f5a6c60 0x7ffe7f5a6c64 0x7ffe7f5a6c68 0x7ffe7f5a6c6c 0x7ffe7f5a6c70 0x7ffe7f5a6c74 0x7ffe7f5a6c78 0x7ffe7f5a6c7c 0x7ffe7f5a6c80 0x7ffe7f5a6c84
0x7ffe7f5a6c90 0x7ffe7f5a6c94 0x7ffe7f5a6c98 0x7ffe7f5a6c9c 0x7ffe7f5a6ca0 0x7ffe7f5a6ca4 0x7ffe7f5a6ca8 0x7ffe7f5a6cac 0x7ffe7f5a6cb0 0x7ffe7f5a6cb4
value:
11 12 13 14 15 16 17 18 19 10
1 2 3 4 5 6 7 8 9 0
Process finished with exit code 0
可见,在交换之后,每个容器中的元素的地址并没有发生改变。
作为对比,看一下vector交换之后会发生什么:
#include
#include
int main() {
std::vector vi1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
std::vector vi2 = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
for(const auto& i : vi1){
std::cout << &i << " ";
}
std::cout << std::endl;
for(const auto& i : vi2){
std::cout << &i << " ";
}
std::cout << std::endl;
using std::swap;
swap(vi1, vi2);
std::cout << "after swap:\n";
for(const auto& i : vi1){
std::cout << &i << " ";
}
std::cout << std::endl;
for(const auto& i : vi2){
std::cout << &i << " ";
}
std::cout << std::endl;
std::cout << "value:\n";
for(const auto& i : vi1){
std::cout << i << " ";
}
std::cout << std::endl;
for(const auto& i : vi2){
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
输出:
0x5652e8c6fe70 0x5652e8c6fe74 0x5652e8c6fe78 0x5652e8c6fe7c 0x5652e8c6fe80 0x5652e8c6fe84 0x5652e8c6fe88 0x5652e8c6fe8c 0x5652e8c6fe90 0x5652e8c6fe94
0x5652e8c6fea0 0x5652e8c6fea4 0x5652e8c6fea8 0x5652e8c6feac 0x5652e8c6feb0 0x5652e8c6feb4 0x5652e8c6feb8 0x5652e8c6febc 0x5652e8c6fec0 0x5652e8c6fec4
after swap:
0x5652e8c6fea0 0x5652e8c6fea4 0x5652e8c6fea8 0x5652e8c6feac 0x5652e8c6feb0 0x5652e8c6feb4 0x5652e8c6feb8 0x5652e8c6febc 0x5652e8c6fec0 0x5652e8c6fec4
0x5652e8c6fe70 0x5652e8c6fe74 0x5652e8c6fe78 0x5652e8c6fe7c 0x5652e8c6fe80 0x5652e8c6fe84 0x5652e8c6fe88 0x5652e8c6fe8c 0x5652e8c6fe90 0x5652e8c6fe94
value:
11 12 13 14 15 16 17 18 19 20
1 2 3 4 5 6 7 8 9 0
Process finished with exit code 0
可见,vector的交换实际上是拿指针做了一些小把戏,(实际上除数组和字符串以外的容器的交换都使用这种方式),并没有规规矩矩去逐字节交换,因此速度比较快。
以上两种方式,虽然行为上是一样的,但是实现的不同导致其性能差异很大,指向array的迭代器、指针、引用等,在交换之后仍然指向原来那个数组中的元素(内存)。指向vector中的迭代器的指针、引用和迭代器,在交换操作之后,会指向另一个容器。对string调用交换操作将导致指针、引用,迭代器失效。