c++ std::vector的元素是否单独存储在内存中?

but5z9lq  于 2023-08-09  发布在  其他
关注(0)|答案(3)|浏览(90)

提问:

我尝试打印向量中元素的字节数和内存地址。结果,我看到一个内存地址和一个字节数。向量的元素是分开存储的吗?如果是这样,为什么我的代码给予我的向量只有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.

6ojccjat

6ojccjat1#

一个vector使用多少字节?

向量在两个地方使用内存:1.在向量对象本身内,以及2.在堆上,其中存储向量元素。
编译器实现者在如何分配这些内存方面有很大的自由度。然而,通常情况下,矢量对象本身包含大小不改变的部分。以下是我在Microsoft的实现中发现的:
1.指向堆上数据开头的指针,即指向第一个数据元素的指针。
1.指向数据末尾的指针,即最后一个数据元素之后的一个元素。使用此指针,capacity()计算为end - first
1.一种指针,它标志着最后一个正在使用的元素,即指向最后一个正在使用的数据元素后面的元素的指针。使用此指针,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字节。很明显,vector对象中存储了第四个元素,因为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


在阅读微软的头文件<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

8yparm6h

8yparm6h2#

向量中的数据被动态分配并存储在另一个内存位置,它不是向量的一部分,并且向量只有指向该内存的指针。分配的内存是连续的,因此所有分配的字节在内存中都是相邻的。
在你的例子中,类std::vector的大小是24字节,内存中其他地方额外分配的内存大小是40字节。因此,总共64字节将分配在您的计算机内存中。

smdncfj3

smdncfj33#

sizeof(...)测量对象的大小。它与std::vector的元素个数无关。写colour.size()来计算。使用向量sizeof(std::vector) == 24是因为它包含指向数据的指针、当前元素数和分配数据的容量,每个在您的架构上占用8个字节。不同的实现可能会以不同的方式实现它。
是的,正如你所看到的,指针的位置每次增加8,因为vector的数据是连续存储的。

相关问题