对数组做交换(swap)会发生什么?

在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调用交换操作将导致指针、引用,迭代器失效。

你可能感兴趣的:(C++,c++,容器)