2015-10-19 2 views
1

У меня есть структура воксельной как:станд :: shared_ptr занимает намного больше места в памяти, чем вектор

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; 
    } 
}; 

У меня есть очень большие п для числа вокселей.

int n = 300 * 300 * 300; 

Теперь, когда я инициализирую вокселы вектором, он занимает приблизительно 79 МБ в ОЗУ.

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

Но это требует более 2 ГБ, когда я инициализирую его таким образом, используя shared_ptr и переполнение стека.

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 

Update: Я также попытался с этим петлю вместо толчка назад, но результат тот же. Теперь у меня есть общий смысл, почему это происходит.

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; 
    } 
+5

Помните, что когда вы задаете размер вектора (используя, например, конструктор, как и вы), а затем вызываете 'push_back', вы увеличиваете размер вектора. Поэтому в вашем примере вы создаете вектор с элементами '2 * n'. Затем вам нужно запомнить накладные расходы на хранение самого указателя, а в 64-битной системе указатель равен 8 байтам по сравнению с вашей структурой из 3 байтов. –

+0

Это переполнение стека? Ты уверен? –

+0

дает ошибку std :: bad_alloc в ячейке памяти. Это, как правило, из-за переполнения, верно? –

ответ

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

собирается занять до sizeof(voxel) * n байт памяти. Когда вы переходите на общий указатель, теперь у вас будет стоимость общего указателя и voxel. Это было бы equivilent к

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

Где sizeof(std::shared_ptr<voxel>), вероятно, будет 16 байт.

Вы также тратить много места в вашем втором примере, как вы заявляете

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

который собирается создать n пустые shared_ptr с, а затем вы push_back еще n не пустые shared_ptr s, так что вы Doulbe размер вектора. Если вы хотите заранее выделить размер vector, то вы должны использовать

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

Несомненно, vi.reserve (n)? – Jeremy

+0

@Jeremy Правильно. Отредактированный ответ. Благодарю. – NathanOliver

4

Ну, voxel и shared_ptr<voxel> не то же самое, так что я не совсем понимаю, почему вы думаете, что они должны иметь одинаковый размер , A shared_ptr<voxel> представляет, как минимум, размер voxelплюс указатель и некоторые данные подсчета ссылок. Это все должно быть где-то сохранено.

Ваш второй пример также недостатки в том, что он имеет в два раза больше элементов, как и в первом примере: вы инициализацию с n элементами «нулевой указатель», то push_backn больше.

+1

Downvote по какой причине, маглов? –

+0

не DV, но я думаю, что ваш размер неправильный. «shared_ptr» - это, вероятно, 2 указателя, плюс у вас есть размер того, на что они указывают. – NathanOliver

+1

@NathanOliver: точное содержание (а) не указано, (b) не имеет значения. Ключевым моментом является «конечно, он больше». Однако вы правы в том, что я пропустил «по крайней мере», что я намеревался. –

Смежные вопросы