代码之家  ›  专栏  ›  技术社区  ›  Meniev

std::向量的元素是否单独存储在存储器-C++中?

  •  -2
  • Meniev  · 技术社区  · 2 年前

    问题

    我试图打印矢量中元素的字节数和内存地址。结果,我看到了一个内存地址和一个字节数。向量的元素是否单独存储?如果是的话,为什么我的代码告诉我向量只有24个字节?

    我尝试了什么

    #include <iostream>
    #include <vector>
    
    int main(){
        std::vector<const char *> colour = {"Microsoft", "Apple", "DELL", "Accer", "Lenovo", "hp"};
        std::cout << "VectorSize : " << sizeof(colour) << "\n" << std::endl;
        for(int i = 0; i < colour.size(); i++){
            std::cout << colour[i] << " is " << sizeof(colour[i]) << " byte at " << &colour[i] << "." << std::endl;
        }
    }
    

    结果:

    VectorSize : 24
    
    Microsoft is 8 byte at 0x27b5a7c6220.
    Apple is 8 byte at 0x27b5a7c6228.
    DELL is 8 byte at 0x27b5a7c6230.
    Accer is 8 byte at 0x27b5a7c6238.
    Lenovo is 8 byte at 0x27b5a7c6240.
    
    2 回复  |  直到 2 年前
        1
  •  3
  •   Pepijn Kramer    2 年前

    矢量中的数据是动态分配的,并存储在另一个内存位置,它不是矢量的一部分,矢量只有一个指向该内存的指针。分配的内存是连续的,因此所有分配的字节在内存中都是相邻的。

    在您的情况下,类std::vector的大小是24字节,内存中其他地方额外分配的内存的大小是40字节。因此,总共64个字节将被分配到您的计算机内存中。

        2
  •  2
  •   templatetypedef    2 年前

    sizeof(...) 测量对象的大小。它与 std::vector 有写 colour.size() 来计算。带矢量 sizeof(std::vector) == 24 因为它包含指向数据的指针、当前元素数和分配数据的容量,每个元素在您的体系结构上占用8个字节。不同的实现可能会以不同的方式实现它。

    是的,您可以看到指针的位置每次增加8,因为矢量的数据是连续存储的。

        3
  •  2
  •   tbxfreeware    2 年前

    一个向量使用多少字节?

    矢量在两个地方使用内存:1。在矢量对象本身内,以及2。在堆上,存储向量元素。

    编译器实现者在如何分配内存方面有很大的自由度。但是,通常情况下,矢量对象本身包含大小不变的部分。以下是我在Microsoft的实现中发现的内容:

    1. 指向堆上数据开头的指针,即指向第一个数据元素的指针。

    2. 指向数据末尾的指针,即最后一个数据元素之外的一个元素。使用该指针, capacity() 计算为 end - first

    3. 标记最后一个使用中的元素的指针,即指向最后一个数据元素后面元素的指针。利用该指针, size() 计算为 last - first

    数据元素存储在堆上,可能与其他特定于实现的信息一起存储(或不存储)。

    对于给定的矢量 v ,假设堆上只存储了数据,则使用的字节数为:

    sizeof(v) + (v.data() == nullptr ? 0 : v.capacity() * sizeof(*v.data()))
    

    原始问题中的向量是指针的向量,特别是指向 const char 。矢量由 initializer_list 有6个 string literals 。字符串文字存储在静态内存中,而指向它们的指针存储在堆中。据推测,能力分配为6,但我认为细节是具体实施的。每个元素的大小是数据指针的大小,通常是 sizeof(std::size_t)

    这里有一个简短的程序来计算使用的字节总数。希望最初的海报能在他的系统上运行,并告诉我们他得到了什么。

    #include <cstddef>
    #include <iostream>
    #include <vector>
    int main()
    {
        std::vector<const char*> v = { "Microsoft", "Apple", "DELL", "Accer", "Lenovo", "hp" };
        std::cout << std::boolalpha
            << "sizeof(v)           : " << sizeof(v)
            << "\nv.size()            : " << v.size()
            << "\nv.capactity()       : " << v.capacity()
            << "\nv.data() == nullptr : " << (v.data() == nullptr)
            << "\nv.data()            : " << v.data()
            << "\nsizeof(*v.data())   : " << sizeof(*v.data())
            << "\nsizeof(std::size_t) : " << sizeof(std::size_t)
            << "\nTotal bytes used    : " << sizeof(v) + (v.data() == nullptr ? 0 : v.capacity() * sizeof(*v.data()))
            << "\n\n"
            ;
        return 0;
    }
    

    我在MSVC上运行,目标是x64,所以我的指针每个是8字节。显然,矢量对象中存储了第四项,因为 sizeof(v) 32岁而不是24岁。

    sizeof(v)           : 32
    v.size()            : 6
    v.capactity()       : 6
    v.data() == nullptr : false
    v.data()            : 000002952A005030
    sizeof(*v.data())   : 8
    sizeof(std::size_t) : 8
    Total bytes used    : 80
    

    在阅读Microsoft的标头源代码时 <vector> ,我找到了上面提到的三个指针。它们存储在名为 _Mypair _Mypair._Myval2 。但是,我找不到 _Mypair._Myval1 ,这大概是第四个项目。

    当我以x86为目标重新编译时,大小减少了一半。这很有道理,因为 std::size_t ,用于指针的大小,已将其大小缩减为4个字节。

    sizeof(v)           : 16
    v.size()            : 6
    v.capactity()       : 6
    v.data() == nullptr : false
    v.data()            : 00AEC640
    sizeof(*v.data())   : 4
    sizeof(std::size_t) : 4
    Total bytes used    : 40