pragma упаковать контейнеры stl

Когда я объявляю такую ​​структуру:

#pragma pack(1)
structure MyStruct{
    uint32_t first;
    uint8_t second;
};
#pragma pack()

Я, очевидно, хочу, чтобы это заняло 5 байтов памяти. Как тогда поведет себя такой вектор:

std::vector<MyStruct> MyVec;

Или такая карта:

std::map<MyStruct> MyMap;

Будут ли они подчиняться запрошенному выравниванию? Могу ли я заставить структуры STL сделать это?


person Dejwi    schedule 01.07.2013    source источник
comment
Вы говорите об упаковке внутренних данных контейнеров stl или структуры, содержащей контейнеры stl?   -  person Borgleader    schedule 01.07.2013
comment
Упаковка внутренних данных. Я хочу, чтобы MyVec или MyMap были как можно меньше.   -  person Dejwi    schedule 01.07.2013


Ответы (3)


При условии, что какой-то компилятор может полностью игнорировать #pragma, да, #pragma влияет на определение типа, поэтому сохранение этого типа в векторе (например) означает, что сохраненное будет упаковано.

#include <iostream>
#include <vector>

typedef unsigned long uint32_t;
typedef unsigned char uint8_t;

struct MyStruct0{
    uint32_t first;
    uint8_t second;
};

#pragma pack(1)
struct MyStruct{
    uint32_t first;
    uint8_t second;
};
#pragma pack()

int main(){ 
    std::vector<MyStruct0> a;

    std::vector<MyStruct> b;

    std::cout << "Unpacked size: " << sizeof(a[0]) << "\n";
    std::cout << "Packed size: " << sizeof(b[0]) << "\n";
    return 0;
}

Результат:

Unpacked size: 8
Packed size: 5
person Jerry Coffin    schedule 01.07.2013
comment
IMO, вам лучше показать разницу в байтах b[1] - b[0], sizeof основан только на типах... - person Balog Pal; 01.07.2013
comment
он также требует [0] использования value_type и value_type в качестве параметра шаблона... :) - person Balog Pal; 01.07.2013
comment
Я думаю, что есть более сильный пример для случая std::vector: MyStruct0 ms0_array[2]; MyStruct ms_array[2]; std::cout << "Unpacked array: " << sizeof(ms0_array) << std::endl; std::cout << "Packed array: " << sizeof(ms_array) << std::endl; Вы также должны знать, что включение упаковки может привести к замедлению доступа к данным. - person paxos1977; 02.07.2013

std::vector должен быть совместим по макету с простым массивом C=style того же типа. Таким образом, у него нет другого выбора, кроме как разместить их в размере, который вы установили для структуры.

Для других коллекций, основанных на узлах, зависит от реализации, как создаются узлы, какие дополнительные байты там появляются.

person Balog Pal    schedule 01.07.2013

Размер действительно имеет здесь значение? Похоже на преждевременную оптимизацию.

В любом случае, для std::vector он обычно (зависит от реализации) содержит 2 переменные-члены: размер и указатель на данные. Поэтому, если у вас их МНОГО, упаковка не сильно изменится (и, прежде чем вы спросите, упаковка данных ни на что не повлияет, потому что в любом случае это непрерывный кусок памяти, потому что он должен быть совместим с C).

Что касается карты, я менее уверен в ее внутренней структуре, но опять же упаковка, вероятно, не сильно повлияет, поскольку IIRC часто реализуется как сбалансированное дерево. Итак, опять же, если у вас их много, много, здесь не так много выигрыша.

Изменить: Кроме того, я открыл заголовок вектора MSVC, и, похоже, есть инструкции игнорировать упаковку прагмы (а именно прагма в верхней части файла и прагма в нижней части).

person Borgleader    schedule 01.07.2013
comment
Насколько я знаю, std::vector обычно имеет 3 переменных-члена: размер, указатель на данные и емкость. И, к сожалению, мне приходится играть с векторами, что занимает до нескольких ГБ памяти. - person Dejwi; 01.07.2013
comment
У вас есть несколько векторов, которые в сумме составляют до ГБ памяти из нескольких больших? Если это последняя упаковка, структура выполнит 99% работы. - person Borgleader; 01.07.2013
comment
Несколько и из-за этого я ищу любую оптимизацию памяти. - person Dejwi; 01.07.2013