Здравствуйте Алекс, Вы писали:
А>Здравствуйте Vi2, Вы писали:
Vi2>>Здравствуйте CAMAD, Вы писали:
А>[]
Vi2>>Это важно в любом случае, потому что это соответствие должно быть на уровне рефлексов! Выделил через new[], удали через delete[]. Выделил через new, удали через delete. А всю работу по оптимизации оставь компилятору — он это сделает без ошибок, в отличие от программиста!
А>довольно наивно
но верно
такие рефлексы спасают глаза от вылезания из орбит при обнаружении memory leaks
[]
S>Есть еще одна форма вызова ФУНКЦИИ new — можно передать ей указатель уже выделенный кусок памяти о она только вызовет конструктор для него
S>
S> sA* Object = new ( Buffer ) sA ( ... );
S>
Не понял. Какой конструктор может быть у уже выделенного куска памяти? Ты хочешь сказать, можно создать экземпляр какого-либо класса и при этом не вызвать конструктор?
Здравствуйте santucco, Вы писали:
S>Здравствуйте Алекс, Вы писали:
А>>Здравствуйте Vi2, Вы писали:
Vi2>>>Здравствуйте CAMAD, Вы писали:
А>>[]
Vi2>>>Это важно в любом случае, потому что это соответствие должно быть на уровне рефлексов! Выделил через new[], удали через delete[]. Выделил через new, удали через delete. А всю работу по оптимизации оставь компилятору — он это сделает без ошибок, в отличие от программиста!
А>>довольно наивно S>но верно S>такие рефлексы спасают глаза от вылезания из орбит при обнаружении memory leaks
согласен, рефлекс нужный. Можно даже в резюме писать: "Имею рефлекс удалять все массивы, выделенные new[] через delete[]".
Здравствуйте Алекс, Вы писали:
А>Здравствуйте santucco, Вы писали:
А>[]
S>>Есть еще одна форма вызова ФУНКЦИИ new — можно передать ей указатель уже выделенный кусок памяти о она только вызовет конструктор для него
S>>
S>> sA* Object = new ( Buffer ) sA ( ... );
S>>
А>Не понял. Какой конструктор может быть у уже выделенного куска памяти? Ты хочешь сказать, можно создать экземпляр какого-либо класса и при этом не вызвать конструктор?
Попробую объяснить популярно...
Пори создании объекта в динамической памяти выполняются две вещи: 1)выделение куска памяти, достаточного для размещения объекта; 2) инициализация этого куска памяти с помощью конструктора класса.
Обычная форма функции new вызывает operator new для выделения куска памати и затем вызывает конструктор класса, который инициализирует этот кусок памяти.
Форма функции new, которую я описал, просто вызывает конструктор для инициализации переданного ей куска памяти.
Здравствуйте Alex Smirnov, Вы писали:
AS>Здравствуйте achp, Вы писали:
A>>Здравствуйте LA Jazz, Вы писали:
LJ>>>Здравствуйте achp, Вы писали:
A>>>>Ну так перечитай!
LJ>>>Мне кажется, что как раз тебе и надо перечитать заново. А там написано вот что: LJ>>>void* operator new(size_t) LJ>>>void operator delete(void *)
LJ>>>void* operator new[](size_t) LJ>>>void operator delete[](void *)
A>>См. ответ мсье Смирнову.
AS>А ВАМ стоит посмотреть исходники!!! Там черным по белому: AS>void * operator new( size_t cb ) AS>{ AS> void *res = _nh_malloc( cb, 1 );
AS> RTCCALLBACK(_RTC_Allocate_hook, (res, cb, 0));
AS> return res; AS>} AS> А malloc() и её инкарнации ВСЕГДА возвращали void*. И было бы глупо возвращать что то иное!!!
Молодой человек, Вы смотрите исходники перегруженного ОПЕРАТОРА new. Это всего-навсего реализация стратегии выделения памяти.
хъ
S>Попробую объяснить популярно... S>Пори создании объекта в динамической памяти выполняются две вещи: 1)выделение куска памяти, достаточного для размещения объекта; 2) инициализация этого куска памяти с помощью конструктора класса.
S>Обычная форма функции new вызывает operator new для выделения куска памати и затем вызывает конструктор класса, который инициализирует этот кусок памяти.
S>Форма функции new, которую я описал, просто вызывает конструктор для инициализации переданного ей куска памяти.
Это все понятно, а как быть если класс имеет виртуальные функции?
Здравствуйте Алекс, Вы писали:
А>Здравствуйте santucco, Вы писали:
А>хъ
S>>Попробую объяснить популярно... S>>Пори создании объекта в динамической памяти выполняются две вещи: 1)выделение куска памяти, достаточного для размещения объекта; 2) инициализация этого куска памяти с помощью конструктора класса.
S>>Обычная форма функции new вызывает operator new для выделения куска памати и затем вызывает конструктор класса, который инициализирует этот кусок памяти.
S>>Форма функции new, которую я описал, просто вызывает конструктор для инициализации переданного ей куска памяти.
А>Это все понятно, а как быть если класс имеет виртуальные функции?
А в чем проблема?
Наличие виртуальных функций подразумевает наличие указателя на vtbl.
Инициализацией этого указателя занимается конструктор ( на самом деле, конструктор делает гораздо больше действий, чем написано в коде cpp'шном коде конструктора ).
Здравствуйте santucco, Вы писали:
S>Здравствуйте Alex Smirnov, Вы писали:
AS>>Здравствуйте achp, Вы писали:
A>>>Здравствуйте LA Jazz, Вы писали:
LJ>>>>Здравствуйте achp, Вы писали:
A>>>>>Ну так перечитай!
LJ>>>>Мне кажется, что как раз тебе и надо перечитать заново. А там написано вот что: LJ>>>>void* operator new(size_t) LJ>>>>void operator delete(void *)
LJ>>>>void* operator new[](size_t) LJ>>>>void operator delete[](void *)
A>>>См. ответ мсье Смирнову.
AS>>А ВАМ стоит посмотреть исходники!!! Там черным по белому: AS>>void * operator new( size_t cb ) AS>>{ AS>> void *res = _nh_malloc( cb, 1 );
AS>> RTCCALLBACK(_RTC_Allocate_hook, (res, cb, 0));
AS>> return res; AS>>} AS>> А malloc() и её инкарнации ВСЕГДА возвращали void*. И было бы глупо возвращать что то иное!!! S>Молодой человек, Вы смотрите исходники перегруженного ОПЕРАТОРА new. Это всего-навсего реализация стратегии выделения памяти.
Уважаемый пианист! прочитайте свой девиз(подпись) несколько раз! может это ВАМ поможет! И можно наверно прекратить этот бестолковый базар.
Здравствуйте Alex Smirnov, Вы писали:
AS>Здравствуйте santucco, Вы писали:
S>>Здравствуйте Alex Smirnov, Вы писали:
AS>>>Здравствуйте achp, Вы писали:
A>>>>Здравствуйте LA Jazz, Вы писали:
LJ>>>>>Здравствуйте achp, Вы писали:
A>>>>>>Ну так перечитай!
LJ>>>>>Мне кажется, что как раз тебе и надо перечитать заново. А там написано вот что: LJ>>>>>void* operator new(size_t) LJ>>>>>void operator delete(void *)
LJ>>>>>void* operator new[](size_t) LJ>>>>>void operator delete[](void *)
A>>>>См. ответ мсье Смирнову.
AS>>>А ВАМ стоит посмотреть исходники!!! Там черным по белому: AS>>>void * operator new( size_t cb ) AS>>>{ AS>>> void *res = _nh_malloc( cb, 1 );
AS>>> RTCCALLBACK(_RTC_Allocate_hook, (res, cb, 0));
AS>>> return res; AS>>>} AS>>> А malloc() и её инкарнации ВСЕГДА возвращали void*. И было бы глупо возвращать что то иное!!! S>>Молодой человек, Вы смотрите исходники перегруженного ОПЕРАТОРА new. Это всего-навсего реализация стратегии выделения памяти.
AS>Уважаемый пианист! прочитайте свой девиз(подпись) несколько раз! может это ВАМ поможет! И можно наверно прекратить этот бестолковый базар.
Пациент скорее мертв, чем жив...
Это печально
Здравствуйте santucco, Вы писали:
S>Здравствуйте Алекс, Вы писали:
А>>Здравствуйте santucco, Вы писали:
А>>хъ
S>>>Попробую объяснить популярно... S>>>Пори создании объекта в динамической памяти выполняются две вещи: 1)выделение куска памяти, достаточного для размещения объекта; 2) инициализация этого куска памяти с помощью конструктора класса.
S>>>Обычная форма функции new вызывает operator new для выделения куска памати и затем вызывает конструктор класса, который инициализирует этот кусок памяти.
S>>>Форма функции new, которую я описал, просто вызывает конструктор для инициализации переданного ей куска памяти.
А>>Это все понятно, а как быть если класс имеет виртуальные функции? S>А в чем проблема? S>Наличие виртуальных функций подразумевает наличие указателя на vtbl. S>Инициализацией этого указателя занимается конструктор ( на самом деле, конструктор делает гораздо больше действий, чем написано в коде cpp'шном коде конструктора ).
получается vtbl распределяется отдельно от экземпляра класса? И деструктор потом грохает эту vtbl?
Здравствуйте Алекс, Вы писали:
А>получается vtbl распределяется отдельно от экземпляра класса? И деструктор потом грохает эту vtbl?
Нет, конструктор только инициализирует указатель на УЖЕ ГОТОВУЮ vtbl. А деструктор с vtbl вообще ничего не делает
Где сама vtbl хранится — зависит от компилятора. У gcc она расположена в сегменте кода, если мне не изменяет память. Если есть желание, могу взглянуть...
Здравствуйте santucco, Вы писали:
S>Здравствуйте Алекс, Вы писали:
А>>получается vtbl распределяется отдельно от экземпляра класса? И деструктор потом грохает эту vtbl?
S>Нет, конструктор только инициализирует указатель на УЖЕ ГОТОВУЮ vtbl. А деструктор с vtbl вообще ничего не делает S>Где сама vtbl хранится — зависит от компилятора. У gcc она расположена в сегменте кода, если мне не изменяет память. Если есть желание, могу взглянуть...
???
Что значит уже готовую vtbl. Из всего вышесказанного тобой я представляю такую картину:
void* pv = malloc(sizeof(MyClass));//ни о какой vtbl и речи нет
MyClass* m = new(pv) MyClass;//а тут она уже появилась!
Здравствуйте CAMAD, Вы писали:
CAMAD>Здравствуйте m.a.g., Вы писали: CAMAD>.... ...>>То ли я туплю? Все делают одну и ту же ошибку. Удалять надо так: ...>>
...>>delete[] pSA;
...>>
CAMAD>Это, конечно, важно для типов с нетривиальными деструкторами. Но для встроенных типов, например, не имеет никакого значения, каким delete удалять их массив.
Покажи мне цитату стандарта, в которой это сказано. А если не найдешь — подумай, одним ли MSVC++ ограничивается мир компиляторов.
Здравствуйте CAMAD, Вы писали:
CAMAD>Здравствуйте Андрей Тарасевич, Вы писали:
АТ>>И из чего же это следует?
CAMAD>А это следует например из очевидной примитивности кода деструктора для встроенного типа.
Только вот из этой примитивности не следует то, что освободится именно нужный кусок памяти.
Придумать можно сколько угодно способов организации кучи, в том числе и таких, для который
разница между delete и delete[] будет жизненно важна.
Здравствуйте Алекс, Вы писали:
А>Здравствуйте santucco, Вы писали:
S>>Здравствуйте Алекс, Вы писали:
А>>>получается vtbl распределяется отдельно от экземпляра класса? И деструктор потом грохает эту vtbl?
S>>Нет, конструктор только инициализирует указатель на УЖЕ ГОТОВУЮ vtbl. А деструктор с vtbl вообще ничего не делает S>>Где сама vtbl хранится — зависит от компилятора. У gcc она расположена в сегменте кода, если мне не изменяет память. Если есть желание, могу взглянуть...
А>??? А>Что значит уже готовую vtbl. Из всего вышесказанного тобой я представляю такую картину: А>
А>void* pv = malloc(sizeof(MyClass));//ни о какой vtbl и речи нет
А>MyClass* m = new(pv) MyClass;//а тут она уже появилась!
А>
А>Объясни!
Готовую vtbl — это значит, что для каждого класса компилятор создает массив указателей на виртуальные методы. Конструктор каждого класса, имеющего виртуальные методы, инициализирует указатель на vtbl указателем на vtbl, соответствующую данному классу.
Размер каждого экземпляра класса складывается из суммы размеров всех его членов-данных + возможное выравнивание + (если у класса есть хотя бы один виртуальный метод) размер указателя на vtbl (в случае множественного наследования их может быть несколько). Поэтому sizeof (MyClass) уже включает размер указателя (если MyClass имеет виртуальные методы, естественно ). Даже если класс не имеет ни одного члена-данного, но имеет хотя бы один виртуальный метод, то его размер, будет равен размеру указателя на vtbl ( для x86 — 4 байта ). Можешь проверить
P.S. Под "имеет виртуальные методы" подразумевается, что либо в классе объявлен хотя бы один виртуальный метод, либо класс наследует от класса, имеющего виртуальные методы