Страницы

Поиск по вопросам

понедельник, 30 декабря 2019 г.

Экономим память с динамическими массивами от C++

#оптимизация #cpp


Здравствуйте, при работе с динамическими массивами приходится выделять память под
переменную, чтобы запомнить размер этого массива. Но ведь оператор new[] выделяет из
кучи не только память под массив, но непосредственно перед массивом выделяется место
под размер этого массива, чтобы delete[] смог выполнить нужное количество деструкторов.
Так вот у меня появилась мысль:"а зачем собственно дважды выделять место для сохранения
размера массива?"
Как пример, вот такой вот код:
class A
{
public:
    ~A(){}//предположим, что некий деструктор определен
};
class B
{
    A* pa;
    //int sz; ведь нам не нужно хранить размер массива
public:
    B(int n) //динамически конструируем массив, получив его размер
    {
        pa=new A[n];
        //sz=n; операция стала лишней - ещё и размер кода сокращается! 
        //мелочь, а приятно
    }
    void go() //проходим по массиву
    {
        //for(int i=0;i


Ответы

Ответ 1



Нельзя закладываться на то, что по смещению -1 лежит размер массива. Кажется это не гарантируется стандартом. Да и килобайты не волнуют никого уже давно. ЗЫ: по-моему даже в реализации vector из gcc хранится три указателя, на начало, конец и конец выделенной памяти (хотя это не по делу, там malloc-ом память выделяется).

Ответ 2



Из пушки по воробьям, по-моему. Позаботьтесь о будущих поколениях - напишите проще.

Ответ 3



Полагаться нельзя, и вот почему: когда я перегружал оператор new, то заметил интересное поведение компилятора от MS. Если в классе A пользователь не определил деструктор, то памяти выделялось ровно столько, сколько нужно для размещения объектов, без "хвостика", в котором записывается кол-во объектов, для которых была выделена память. Предположение очевидно - этот "хвостик" нужен для того, чтобы в delete получить адреса всех объектов и вызвать для них деструкторы, а раз пользователь деструктор не определил, стало быть, можно очистить все тривиальным образом и "хвостик" не нужен. Теперь представьте что пользователь не определил деструктор и по смещению "-1" фактически лежит мусор. Как вариант можно сделать класс B шаблонным и проверять есть ли у класса А определенный пользователем деструктор или нет, но тогда можно забыть об использовании неPOD-типов. Понятно, что это уже внутренняя оптимизация, наличие или отсутствие которой не гарантируется в других компиляторах или компиляторах других версий. Т.ч. лучше, как уже было сказано, делать все "легальным" путем.

Ответ 4



К вышесказанному хочу дополнить, что деструктор у класса A будет всегда создан, если не программистом, то компилятором, и это никак не влияет на описанную схему выделения/освобождения памяти.

Комментариев нет:

Отправить комментарий