std::shared_ptr 比矢量占用更多的内存 space

std::shared_ptr takes lot more memory space than vector

我的体素结构为:

struct voxel
{
    unsigned char R, G, B;
    voxel()
    {
        R = G = B = 0;
    }
    //parameteric contructor with parameters
    voxel(unsigned char pR, unsigned char pG, unsigned char pB)
    {
        R = pR; G = pG; B = pB;
    }
};

我的体素数 n 非常大。

int n = 300 * 300 * 300;

现在,当我用矢量初始化体素时,它需要大约 79 MB 的 RAM。

std::vector< voxel > vi(n);

但是当我使用 shared_ptr 以这种方式初始化它并且堆栈溢出时它需要超过 2 GB。

std::vector< std::shared_ptr<voxel> > vi(n);
for (size_t i = 0; i < n; i++)
{
    vi.push_back(std::shared_ptr<voxel>(new voxel()));
}

这种行为的原因是什么?我该如何避免?

补充说明:

std::vector< std::shared_ptr<voxel> > vi(n); //statement takes 211 MB alone

更新: 我也尝试过使用这个循环而不是推回,但结果是一样的。我现在大致了解了为什么会发生这种情况。

for (size_t i = 0; i < n; i++)
    {
        vi[i].reset(new voxel());
        vi[i]->B = 0;
        vi[i]->R = 0;
        vi[i]->G = 0;
    }
std::vector< voxel > vi(n);

将占用sizeof(voxel) * n字节内存。当您更改为共享指针时,您现在将拥有共享指针和 voxel 的成本。这相当于

sizeof(voxel) * n + sizeof(std::shared_ptr<voxel>) * n

其中sizeof(std::shared_ptr<voxel>)可能是16字节。

你在声明

的第二个例子中也浪费了很多space
std::vector< std::shared_ptr<voxel> > vi(n);

这将创建 nshared_ptrs 然后你 push_back 另一个 n 非空 shared_ptrs 所以你的大小加倍向量。如果你想预分配 vector 的大小,那么你应该使用

std::vector< std::shared_ptr<voxel> > vi;
vi.reserve(n);

嗯,voxelshared_ptr<voxel> 不是一回事,所以我不太明白为什么您认为它们应该具有相同的大小。一个shared_ptr<voxel>至少代表了一个voxel的大小加上一个指针和一些引用计数信息。这些都必须存储在某个地方。

你的第二个例子也有缺陷,因为它的元素数量是第一个例子的两倍:你用 n "null pointer" 元素初始化然后 push_back n更多