std::array和std::vector的微妙区别

3

我想尝试使用std::array来了解它与std::vector的不同之处。到目前为止,我只发现了一个主要区别。

Sentence sentence = { "Hello", "from", "GCC", __VERSION__, "!" };  
std::array<std::string, 10> a;
std::copy(sentence.begin(), sentence.end(), a.begin());

int i = 0;
for (const auto& e : a)
{
    i++;
    std::cout << e << std::endl;
}
std::cout << i << std::endl;

// outputs 10

i = 0;
for (const auto& e : sentence)
{
    i++;
    std::cout << e << std::endl;
}
std::cout << i << std::endl;

// outputs 5

for (int i = 0; i < a.size(); i++)
    std::cout << i << " " << a[i] << std::endl;

// outputs 0 Hello
// ...
//         4 !
//         5-9 is blank

for (int i = 0; i < sentence.size(); i++)
    std::cout << i << " " << sentence[i] << std::endl;

// outputs 0 Hello
// ...
//         4 !
// stops here


// The following outputs the same as above
i = 0;

for (auto it = a.begin(); it != a.end(); it++)
{
    std::cout << i << " " << *it << std::endl;
    i++;
}
std::cout << i << std::endl;
i = 0;
for (auto it = sentence.begin(); it != sentence.end(); it++)
{
    std::cout << i << " " << *it << std::endl;   
    i++;
}
std::cout << i << std::endl;

据我所见,std::arraysizemax_size是多余的,但是std::vectorsizecapacity可以不同或相同。这甚至可以从以下引用中确认:

数组对象的大小和最大大小始终匹配。

那么为什么std::array有多余的大小函数呢?更重要的是,您是否认为std::array的大小不一定与std::vector的大小相同是一个陷阱,因为向量具有容量?此外,这是否意味着std::array是安全的(即它们像向量一样具有智能指针管理)?

1
最后一句话让我觉得你可能对std::array的实际含义有些困惑;也许可以在这里快速比较一下这里 - Matteo Italia
你可能认为可调整大小与否以及动态分配与静态分配之间的差异更大...此外,需要将大小作为模板参数(从而实现静态分配)。 - Ben Voigt
6
std::arraystd::vector 之间的差异远非微妙。 - Charles Salvia
5个回答

6
为了使其与其他容器兼容。
这样,您可以拥有一个模板函数,它可以接受任何集合,并确保无论是 std::vector 还是 std::array,它都能正常工作。

4
vector中的capacity是指vector的最大容量,可能与其size相同,也可能不同。而sizevector中当前元素的数量。

出于性能考虑,如果您预先知道向量的最大大小(或有猜测),则可以预先确定向量的容量(而不是使用其默认值)。这将显著提高您代码的性能,因为您无需在每次迭代时重新分配内存(添加元素时)。

http://www.cplusplus.com/reference/vector/vector/capacity/


2
更重要的区别在于,std::vector 有一个 resize 函数,而 std::array 没有。
std::array 实例被实例化时(事实上,其大小必须在编译时已知且为常量表达式),它的大小就像普通数组一样是固定的。然而,std::vector 实例可以在运行时被重新调整大小。
此外,不同大小的 std::array 是不同的类型,而不同大小的 std::vector 是相同的类型。
使用 std::array 而不是 std::vector 的唯一原因是 std::array 占用的空间更小、速度更快。 std::vector 需要存储其大小以及指向堆分配的后备存储的指针,该存储可能具有额外的填充来允许调整大小。 std::array 在原地分配(没有间接指针),并且其 size 函数也已静态知道,因此对 std::array.size() 的调用将编译成一个常量(实际上它是一个 constexpr 函数)。

1
稍作解释,关于 std::array,它的设计非常接近实际数组的设计,例如 char[],其中数组的最大大小就是数组的大小。这是因为可以将数组视为具有不可变大小的对象。也就是说,除了完全重新分配内存之外,大小不能被更改。与 std::vector 不同,后者可以设置 capacity 和大小,大小可以从 0 到该 capacity 的任何值,但是一旦超过该 capacity 值,每个新元素都会导致在 vector 内部重新创建和分配基础数组。

1
正如你所指出的,std::array 的大小始终相同。 size() == capacity()。这意味着当您创建一个 std::array<T, 5> 时,您会得到五个对 T 的默认构造函数的调用。另一方面,std::vector<T> 不会默认构造任何元素。在向向量上调用 reserve(5) 仍不会导致任何项被构造。

无论是 std::array 还是 std::vector 都没有“智能指针管理”,至少在我考虑它们的方式中是这样。它们都提供了迭代器类型和像 begin/end/rbegin/rend 这样的函数,让您遍历容器中的元素。当人们说“智能指针”时,我想到的是 shared_ptr/unique_ptr/auto_ptr/etc

一般来说,std::array 存储在栈上,而 std::vector 在堆上分配存储空间。在性能关键的应用程序中,这对于 std::array 是一个很大的优势。在多线程应用程序中,使用堆分配内存比使用栈慢100倍或1000倍。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接