【问题标题】:C array of objects that allow for dynamic allocation允许动态分配的 C 对象数组
【发布时间】:2020-10-01 00:55:13
【问题描述】:

如果我有一个像std::vector 这样的动态分配类。用该对象的元素创建一个数组有多大意义?

我测试了以下内容:

std::vector<int> array[2];

array[0].push_back(10);
array[0].push_back(20);
array[0].push_back(30);


array[1].push_back(40);
array[1].push_back(50);
array[1].push_back(60);

for (auto x : array[0]) {
    std::cout << x << std::endl;
}

for (auto x : array[1]) {
    std::cout << x << std::endl;
}

正确输出值。然而,这实际上是未定义的行为吗?数组元素在内存中是连续定位的。当 std::vector 对象在未指定大小的情况下初始化时,它不会分配任何内存。那么当我们创建一个包含两个元素的数组时,是否分配了任何内存?然后,当我们向std::vector 添加新元素时,我们是否在数组边界之外写入?

【问题讨论】:

  • 向量不会将分配的内存存储在向量对象内。一个向量包含一个大小的 int 和一个指向一些堆分配内存的指针,也许还有其他一些东西。所以向量数组很好,因为当向量增长时,它是被重新分配的堆内存,而这些都不是在向量对象内部(因此不在数组内部)。
  • @JerryJeremiah 哦,是的,这实际上是有道理的。所以我们实际上是在创建一个指针数组。谢谢!

标签: c++ arrays vector


【解决方案1】:

这里没有未定义的行为。

用该对象的元素创建一个数组有多大意义?

这完全取决于您和您的设计考虑。拥有一个向量数组是非常好的。

那么当我们创建一个包含两个元素的数组时,是否分配了任何内存?

是的,数组的内存已分配。

当我们向 std::vector 添加新元素时,我们是否在数组边界之外写入?

std::vector 动态分配内存。默认构造的向量可能会也可能不会分配内存。这取决于实现。在内部,向量可能只是持有指针。

一些实现可能比这更聪明,通过从没有动态分配的固定数量的元素切换到如果要求超过动态分配则使用动态分配。 std::string 实现通常这样做,通过重新利用内部指针存储来保存字符串数据。

请注意,如果您将一些元素推送到一个新向量上,最好在该向量上调用 reserve 以避免随着它的增长而进行不必要的重新分配。

【讨论】:

  • 我认为向量不太可能具有与小字符串优化等效的功能,因为它仅对 1 个 int 或 8 个 chars 有用。对于不一定不常见的字符串,但对于向量......
  • 我不明白为什么这是一个如此疯狂的想法。想象一下std::vector&lt;char&gt;。据我所知,该标准并未排除它。
  • 不,当然不排除,但小字符串很常见,而如果你有一个std::vector&lt;char&gt;,它可能是二进制数据的一些缓冲区,往往更大,对于任何其他value_type它可能完全没用。没有一个令人信服的理由来实现它(并承担在随之而来的存储机制之间切换的成本)。
【解决方案2】:

std::vector&lt;int&gt; 类型的对象具有取决于其实现的固定大小。

考虑以下演示程序。

#include <iostream>
#include <vector>

int main() 
{
    std::vector<int> array[2];

    std::cout << "sizeof( std::vector<int> ) = " 
              << sizeof( std::vector<int> )
              << '\n';
                  
    std::cout << "sizeof( array = " 
              << sizeof( array )
              << '\n';
                      
    std::cout << '\n';
    
    array[0].push_back(10);
    array[0].push_back(20);
    array[0].push_back(30);


    array[1].push_back(40);
    array[1].push_back(50);
    array[1].push_back(60);
    
    std::cout << "sizeof( std::vector<int> ) = " 
              << sizeof( std::vector<int> )
              << '\n';
                  
    std::cout << "sizeof( array = " 
              << sizeof( array )
              << '\n';
                      
}   

它的输出可能看起来像

sizeof( std::vector<int> ) = 24
sizeof( array = 48

sizeof( std::vector<int> ) = 24
sizeof( array = 48

当您向向量添加新元素时,它们的大小不会改变,相应的数组大小也不会改变。

程序结构良好。

类模板std::vector 包含一个指针作为其数据成员,该指针指向它放置其元素的内存。如果没有足够的内存,向量会重新分配它。但是vector类型的对象本身的大小并不依赖于重新分配的内存。

【讨论】:

    猜你喜欢
    • 2011-10-26
    • 2010-09-20
    • 1970-01-01
    • 2011-02-06
    • 2014-12-21
    • 2021-03-17
    • 1970-01-01
    • 2013-02-02
    相关资源
    最近更新 更多