C++ STL array容器和普通数组的比较

C++ 普通数组存储数据的方式一样,C++ 标准库保证使用 array 容器存储的所有元素一定会位于连续且相邻的内存中,通过如下代码也可以验证这一点:
#include <iostream>
#include <array>
using namespace std;
int main()
{
    array<int, 5>a{1,2,3};
    cout << &a[2] << " " << &a[0] + 2 << endl;
    return 0;
}
输出结果为:

004FFD58 004FFD58

可以看到,a 容器中 &a[2] 和 &a[0] + 2 是相等的。因此在实际编程过程中,我们完全有理由去尝试,在原本使用普通数组的位置,改由 array 容器去实现。

用 array 容器替换普通数组的好处是,array 模板类中已经封装好了大量实用的方法,在提高开发效率的同时,代码的运行效率也会大幅提高。

举个例子,我们完全可以使用 array 容器去存储 char* 或 const char* 类型的字符串:
#include <iostream>
#include <array>
using namespace std;
int main()
{
    array<char, 50>a{1,2,3};
    strcpy(&a[0], "https://www.xinbaoku.com/stl");
    printf("%s", &a[0]);
    return 0;
}
输出结果为:

https://www.xinbaoku.com/stl

注意,array 容器的大小必须保证能够容纳复制进来的数据,而且如果是存储字符串的话,还要保证在存储整个字符串的同时,在其最后放置一个\0作为字符串的结束符。此程序中,strcpy() 在拷贝字符串的同时,会自动在最后添加\0

其实,代码中的 &a[0] 还可以用 array 模板类提供的 data() 成员函数来替换:
#include <iostream>
#include <array>
using namespace std;
int main()
{
    array<char, 50>a{1,2,3};
    strcpy(a.data(), "https://www.xinbaoku.com/stl");
    printf("%s", a.data());
    return 0;
}
此程序和上面程序的输出结果完全相同。

注意,容器的迭代器和指针是不能混用的,即上面代码中不能用 a.begin() 来代替 &a[0] 或者 a.data[],这可能会引发错误。

文章前面提到,使用 array 容器代替普通数组,最直接的好处就是 array 模板类中已经为我们写好了很多实用的方法,可以大大提高我们编码效率。例如,array 容器提供的 at() 成员函数,可以有效防止越界操纵数组的情况;fill() 函数可以实现数组的快速初始化;swap() 函数可以轻松实现两个相同数组(类型相同,大小相同)中元素的互换。
#include <iostream>
#include <array>
using namespace std;
int main()
{
    array<char, 50>addr1{"https://www.xinbaoku.com"};
    array<char, 50>addr2{ "https://www.xinbaoku.com/stl" };
    addr1.swap(addr2);
    printf("addr1 is:%s\n", addr1.data());
    printf("addr2 is:%s\n", addr2.data());
    return 0;
}
运行结果为:

addr1 is:https://www.xinbaoku.com/stl
addr2 is:https://www.xinbaoku.com


另外,当两个 array 容器满足大小相同并且保存元素的类型相同时,两个 array 容器可以直接直接做赋值操作,即将一个容器中的元素赋值给另一个容器。比如:
#include <iostream>
#include <array>
using namespace std;
int main()
{
    array<char, 50>addr1{ "https://www.xinbaoku.com" };
    array<char, 50>addr2{ "https://www.xinbaoku.com/stl" };
    addr1 = addr2;
    printf("%s", addr1.data());
    return 0;
}
运行结果为:

https://www.xinbaoku.com/stl


不仅如此,在满足以上 2 个条件的基础上,如果其保存的元素也支持比较运算符,就可以用任何比较运算符直接比较两个 array 容器。示例如下:
#include <iostream>
#include <array>
using namespace std;
int main()
{
    array<char, 50>addr1{ "https://www.xinbaoku.com" };
    array<char, 50>addr2{ "https://www.xinbaoku.com/stl" };
    if (addr1 == addr2) {
        std::cout << "addr1 == addr2" << std::endl;
    }
    if (addr1 < addr2) {
        std::cout << "addr1 < addr2" << std::endl;
    }
    if (addr1 > addr2) {
        std::cout << "addr1 > addr2" << std::endl;
    }
    return 0;
}
运行结果为:

addr1 < addr2

两个容器比较大小的原理,和两个字符串比较大小是一样的,即从头开始,逐个取两容器中的元素进行大小比较(根据 ASCII 码表),直到遇到两个不相同的元素,那个元素的值大,则该容器就大。

总之,读者可以这样认为,array 容器就是普通数组的“升级版”,使用普通数组能实现的,使用 array 容器都可以实现,而且无论是代码功能的实现效率,还是程序执行效率,都比普通数组更高。