Здравствуйте santucco, Вы писали:
S>Здравствуйте Алекс, Вы писали:
А>>Здравствуйте Vi2, Вы писали:
Vi2>>>Здравствуйте CAMAD, Вы писали:
А>>[]
Vi2>>>Это важно в любом случае, потому что это соответствие должно быть на уровне рефлексов! Выделил через new[], удали через delete[]. Выделил через new, удали через delete. А всю работу по оптимизации оставь компилятору — он это сделает без ошибок, в отличие от программиста!
А>>довольно наивно S>но верно S>такие рефлексы спасают глаза от вылезания из орбит при обнаружении memory leaks
согласен, рефлекс нужный. Можно даже в резюме писать: "Имею рефлекс удалять все массивы, выделенные new[] через 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. Под "имеет виртуальные методы" подразумевается, что либо в классе объявлен хотя бы один виртуальный метод, либо класс наследует от класса, имеющего виртуальные методы
Как лучше осуществить возвращение массива структур sA из ф-ии:
1.
void f(sA* pSA, int* count)
{
int nmbSA = 4;
...
sA *pRes = new sA[nmbSA];
... // do something with array
pSA = pRes;
*count = nmbSA;
}
main()
{
int nmbSA = 0;
sA *pSA = 0;
f(pSA, &nmbSA);
if(pSA)
delete pSA;
}
2.
void f(sA* pSA, int count)
{
int nmbSA = 4;
...
sA *pRes = new sA[nmbSA];
... // do something with array
memcpy(pSA, pRes, sizeof(sA)*(__min(nmbSA, count))
delete pRes;
}
main()
{
int nmbSA = 4;
sA *pSA = new sA[nmbSA];
f(pSA, nmbSA);
delete pSA;
}
Здравствуйте LA Jazz, Вы писали:
LJ>Здравствуйте Gosha, Вы писали:
LJ>Но тогда возникает другой вопрос: этично ли заставлять пользователя удалять LJ>указатель. Ведь так и забыть можно про удаление, а это Leaks...
Ну, откровенно говоря, возврат указателя на выделенную внутри функции памать — потенциальный memory leak, как бы он не возвращался — через в параметры или через возвращаемое значение )). User обязательно забудет вызвать delete для этой памяти.
Здравствуйте santucco, Вы писали:
S>Здравствуйте LA Jazz, Вы писали:
LJ>>Здравствуйте Gosha, Вы писали:
LJ>>Но тогда возникает другой вопрос: этично ли заставлять пользователя удалять LJ>>указатель. Ведь так и забыть можно про удаление, а это Leaks... S>Ну, откровенно говоря, возврат указателя на выделенную внутри функции памать — потенциальный memory leak, как бы он не возвращался — через в параметры или через возвращаемое значение )). User обязательно забудет вызвать delete для этой памяти.
Ну так этим и WinAPI грешит, взять хотя бы FormatMessage c его флагом FORMAT_MESSAGE_ALLOCATE_BUFFER — освобождение выделенной памяти остается на вашей совести...
Здравствуйте LA Jazz, Вы писали:
LJ>Здравствуйте santucco, Вы писали:
LJ>А как лучше вернуть массив, если заранее к-во элементов неизвестно LJ>и не заставляя юзера delete делать?
Выделить заведомо больше памяти, передать в функцию указатель на память и ее размер и вернуть количество элементов, положенных в массив — это классический С-шный подход
Или взять STL-реализацию массива (vector), передать его в функцию по ссылке и не мучиться
Здравствуйте Flamer, Вы писали:
F>Здравствуйте santucco, Вы писали:
S>>Здравствуйте LA Jazz, Вы писали:
LJ>>>Здравствуйте Gosha, Вы писали:
LJ>>>Но тогда возникает другой вопрос: этично ли заставлять пользователя удалять LJ>>>указатель. Ведь так и забыть можно про удаление, а это Leaks... S>>Ну, откровенно говоря, возврат указателя на выделенную внутри функции памать — потенциальный memory leak, как бы он не возвращался — через в параметры или через возвращаемое значение )). User обязательно забудет вызвать delete для этой памяти.
F>Ну так этим и WinAPI грешит, взять хотя бы FormatMessage c его флагом FORMAT_MESSAGE_ALLOCATE_BUFFER — освобождение выделенной памяти остается на вашей совести...
No comments
Здравствуйте santucco, Вы писали:
S>Здравствуйте Flamer, Вы писали:
F>>Здравствуйте santucco, Вы писали:
S>>>Здравствуйте LA Jazz, Вы писали:
LJ>>>>Здравствуйте Gosha, Вы писали:
LJ>>>>Но тогда возникает другой вопрос: этично ли заставлять пользователя удалять LJ>>>>указатель. Ведь так и забыть можно про удаление, а это Leaks... S>>>Ну, откровенно говоря, возврат указателя на выделенную внутри функции памать — потенциальный memory leak, как бы он не возвращался — через в параметры или через возвращаемое значение )). User обязательно забудет вызвать delete для этой памяти.
F>>Ну так этим и WinAPI грешит, взять хотя бы FormatMessage c его флагом FORMAT_MESSAGE_ALLOCATE_BUFFER — освобождение выделенной памяти остается на вашей совести... S>No comments
Здравствуйте Flamer, Вы писали:
F>Здравствуйте santucco, Вы писали:
S>>Здравствуйте Flamer, Вы писали:
F>>>Здравствуйте santucco, Вы писали:
S>>>>Здравствуйте LA Jazz, Вы писали:
LJ>>>>>Здравствуйте Gosha, Вы писали:
LJ>>>>>Но тогда возникает другой вопрос: этично ли заставлять пользователя удалять LJ>>>>>указатель. Ведь так и забыть можно про удаление, а это Leaks... S>>>>Ну, откровенно говоря, возврат указателя на выделенную внутри функции памать — потенциальный memory leak, как бы он не возвращался — через в параметры или через возвращаемое значение )). User обязательно забудет вызвать delete для этой памяти.
F>>>Ну так этим и WinAPI грешит, взять хотя бы FormatMessage c его флагом FORMAT_MESSAGE_ALLOCATE_BUFFER — освобождение выделенной памяти остается на вашей совести... S>>No comments
F>Не понял Что имелось в виду? Разъясните, плз..
Имелось ввиду, что не стОит перенимать откровенно неудачные и потенциально опасные приемы, даже если они используются в чьем-либо API.
Здравствуйте santucco, Вы писали:
S>Здравствуйте Flamer, Вы писали:
F>>Здравствуйте santucco, Вы писали:
S>>>Здравствуйте Flamer, Вы писали:
F>>>>Здравствуйте santucco, Вы писали:
S>>>>>Здравствуйте LA Jazz, Вы писали:
LJ>>>>>>Здравствуйте Gosha, Вы писали:
LJ>>>>>>Но тогда возникает другой вопрос: этично ли заставлять пользователя удалять LJ>>>>>>указатель. Ведь так и забыть можно про удаление, а это Leaks... S>>>>>Ну, откровенно говоря, возврат указателя на выделенную внутри функции памать — потенциальный memory leak, как бы он не возвращался — через в параметры или через возвращаемое значение )). User обязательно забудет вызвать delete для этой памяти.
F>>>>Ну так этим и WinAPI грешит, взять хотя бы FormatMessage c его флагом FORMAT_MESSAGE_ALLOCATE_BUFFER — освобождение выделенной памяти остается на вашей совести... S>>>No comments
F>>Не понял Что имелось в виду? Разъясните, плз.. S>Имелось ввиду, что не стОит перенимать откровенно неудачные и потенциально опасные приемы, даже если они используются в чьем-либо API.
Здравствуйте Flamer, Вы писали:
F>Здравствуйте santucco, Вы писали:
S>>Здравствуйте Flamer, Вы писали:
F>>>Здравствуйте santucco, Вы писали:
S>>>>Здравствуйте Flamer, Вы писали:
F>>>>>Здравствуйте santucco, Вы писали:
S>>>>>>Здравствуйте LA Jazz, Вы писали:
LJ>>>>>>>Здравствуйте Gosha, Вы писали:
LJ>>>>>>>Но тогда возникает другой вопрос: этично ли заставлять пользователя удалять LJ>>>>>>>указатель. Ведь так и забыть можно про удаление, а это Leaks... S>>>>>>Ну, откровенно говоря, возврат указателя на выделенную внутри функции памать — потенциальный memory leak, как бы он не возвращался — через в параметры или через возвращаемое значение )). User обязательно забудет вызвать delete для этой памяти.
F>>>>>Ну так этим и WinAPI грешит, взять хотя бы FormatMessage c его флагом FORMAT_MESSAGE_ALLOCATE_BUFFER — освобождение выделенной памяти остается на вашей совести... S>>>>No comments
F>>>Не понял Что имелось в виду? Разъясните, плз.. S>>Имелось ввиду, что не стОит перенимать откровенно неудачные и потенциально опасные приемы, даже если они используются в чьем-либо API.
F>Так я вроде как согласен с этим
Тогда дико извиняюсь за необоснованный наезд
Здравствуйте Alex Smirnov, Вы писали:
AS>Здравствуйте m.a.g., Вы писали:
...>>Здравствуйте PSP, Вы писали:
PSP>>>корректно будет так:
PSP>>>
PSP>>>void f(sA* & pSA, int &count)
PSP>>>{
PSP>>> sA *pRes = new sA[nmbSA];
PSP>>> pSA = pRes;
PSP>>>}
PSP>>>main()
PSP>>>{
PSP>>> f(pSA, nmbSA);
PSP>>> if(pSA)
PSP>>> delete pSA;
PSP>>>}
PSP>>>
...>>То ли я туплю? Все делают одну и ту же ошибку. Удалять надо так: ...>>
...>>delete[] pSA;
...>>
...>>m.a.g. — Ты единственный умный человек в этой толпе!!! AS> и чем народ не устраивает просто sA* p=(sA*)new sA[count];
Я дико извиняюсь за собственную тупость — но я не понял сокровенного смысла этой конструкции
Здравствуйте santucco, Вы писали:
S>Здравствуйте Alex Smirnov, Вы писали:
AS>>Здравствуйте m.a.g., Вы писали:
...>>>Здравствуйте PSP, Вы писали:
PSP>>>>корректно будет так:
PSP>>>>
PSP>>>>void f(sA* & pSA, int &count)
PSP>>>>{
PSP>>>> sA *pRes = new sA[nmbSA];
PSP>>>> pSA = pRes;
PSP>>>>}
PSP>>>>main()
PSP>>>>{
PSP>>>> f(pSA, nmbSA);
PSP>>>> if(pSA)
PSP>>>> delete pSA;
PSP>>>>}
PSP>>>>
...>>>То ли я туплю? Все делают одну и ту же ошибку. Удалять надо так: ...>>>
...>>>delete[] pSA;
...>>>
...>>>m.a.g. — Ты единственный умный человек в этой толпе!!! AS>> и чем народ не устраивает просто sA* p=(sA*)new sA[count]; S>Я дико извиняюсь за собственную тупость — но я не понял сокровенного смысла этой конструкции
На то он и сокровенный!
Зачем нужно придумывать функцию простого выделения памяти
чтоб потом на продолжении долгого времени успешно искать ошибку
Здравствуйте Alex Smirnov, Вы писали:
AS>Здравствуйте santucco, Вы писали:
S>>Здравствуйте Alex Smirnov, Вы писали:
AS>>> и чем народ не устраивает просто sA* p=(sA*)new sA[count]; S>>Я дико извиняюсь за собственную тупость — но я не понял сокровенного смысла этой конструкции
AS> На то он и сокровенный!
AS>Зачем нужно придумывать функцию простого выделения памяти AS>чтоб потом на продолжении долгого времени успешно искать ошибку
Ну, new [] — это не простое выделение памяти, а выделение памяти под массив элементов с вызовом конструктора по умолчанию для каждого элемента массива.
delete [] соответственно вызовет деструктор для каждого элемента массива и освободит выделенную память.
Я сокровенность преобразования sA* к sA* я все-таки не понял .
Если это попытка ВНЕШНЕ (то есть для успокоения зрения )привести указатель на память под массив элементов к указателю на память под элемент, то попытка эта не только наивная, но и опасная с точки зрения утечек памяти.
И она вовсе не дает право освобождать память, выделенную new [], с помощью delete.
Здравствуйте santucco, Вы писали:
S>Здравствуйте Alex Smirnov, Вы писали:
AS>>Здравствуйте santucco, Вы писали:
S>>>Здравствуйте Alex Smirnov, Вы писали:
AS>>>> и чем народ не устраивает просто sA* p=(sA*)new sA[count]; S>>>Я дико извиняюсь за собственную тупость — но я не понял сокровенного смысла этой конструкции
AS>> На то он и сокровенный!
AS>>Зачем нужно придумывать функцию простого выделения памяти AS>>чтоб потом на продолжении долгого времени успешно искать ошибку S>Ну, new [] — это не простое выделение памяти, а выделение памяти под массив элементов с вызовом конструктора по умолчанию для каждого элемента массива. S>delete [] соответственно вызовет деструктор для каждого элемента массива и освободит выделенную память. S>Я сокровенность преобразования sA* к sA* я все-таки не понял . S>Если это попытка ВНЕШНЕ (то есть для успокоения зрения )привести указатель на память под массив элементов к указателю на память под элемент, то попытка эта не только наивная, но и опасная с точки зрения утечек памяти. S>И она вовсе не дает право освобождать память, выделенную new [], с помощью delete.
Ну насколько я знаю компиляторы...они не позволяют без предупреждения оставлять попытки переопределения void* к указателю на другой тип !!!
Здравствуйте m.a.g., Вы писали:
.... ...>То ли я туплю? Все делают одну и ту же ошибку. Удалять надо так: ...>
...>delete[] pSA;
...>
Это, конечно, важно для типов с нетривиальными деструкторами. Но для встроенных типов, например, не имеет никакого значения, каким delete удалять их массив.
Здравствуйте Alex Smirnov, Вы писали:
AS>>>>> и чем народ не устраивает просто sA* p=(sA*)new sA[count]; S>>>>Я дико извиняюсь за собственную тупость — но я не понял сокровенного смысла этой конструкции
AS>>> На то он и сокровенный!
AS>>>Зачем нужно придумывать функцию простого выделения памяти AS>>>чтоб потом на продолжении долгого времени успешно искать ошибку S>>Ну, new [] — это не простое выделение памяти, а выделение памяти под массив элементов с вызовом конструктора по умолчанию для каждого элемента массива. S>>delete [] соответственно вызовет деструктор для каждого элемента массива и освободит выделенную память. S>>Я сокровенность преобразования sA* к sA* я все-таки не понял . S>>Если это попытка ВНЕШНЕ (то есть для успокоения зрения )привести указатель на память под массив элементов к указателю на память под элемент, то попытка эта не только наивная, но и опасная с точки зрения утечек памяти. S>>И она вовсе не дает право освобождать память, выделенную new [], с помощью delete.
AS>Ну насколько я знаю компиляторы...они не позволяют без предупреждения оставлять попытки переопределения void* к указателю на другой тип !!!
Здравствуйте CAMAD, Вы писали:
...>>delete [] pSA; CAMAD>Это, конечно, важно для типов с нетривиальными деструкторами. Но для встроенных типов, например, не имеет никакого значения, каким delete удалять их массив.
Это важно в любом случае, потому что это соответствие должно быть на уровне рефлексов! Выделил через new[], удали через delete[]. Выделил через new, удали через delete. А всю работу по оптимизации оставь компилятору — он это сделает без ошибок, в отличие от программиста!
Здравствуйте achp, Вы писали:
A>Здравствуйте Alex Smirnov, Вы писали:
AS>>>>>> и чем народ не устраивает просто sA* p=(sA*)new sA[count]; S>>>>>Я дико извиняюсь за собственную тупость — но я не понял сокровенного смысла этой конструкции
AS>>>> На то он и сокровенный!
AS>>>>Зачем нужно придумывать функцию простого выделения памяти AS>>>>чтоб потом на продолжении долгого времени успешно искать ошибку S>>>Ну, new [] — это не простое выделение памяти, а выделение памяти под массив элементов с вызовом конструктора по умолчанию для каждого элемента массива. S>>>delete [] соответственно вызовет деструктор для каждого элемента массива и освободит выделенную память. S>>>Я сокровенность преобразования sA* к sA* я все-таки не понял . S>>>Если это попытка ВНЕШНЕ (то есть для успокоения зрения )привести указатель на память под массив элементов к указателю на память под элемент, то попытка эта не только наивная, но и опасная с точки зрения утечек памяти. S>>>И она вовсе не дает право освобождать память, выделенную new [], с помощью delete.
AS>>Ну насколько я знаю компиляторы...они не позволяют без предупреждения оставлять попытки переопределения void* к указателю на другой тип !!!
A>А где здесь void*?
..> achp>> Это просто трёп? или вопрос на самом деле?
Здравствуйте Alex Smirnov, Вы писали:
AS>Здравствуйте achp, Вы писали:
A>>Здравствуйте Alex Smirnov, Вы писали:
AS>>>>>>> и чем народ не устраивает просто sA* p=(sA*)new sA[count]; S>>>>>>Я дико извиняюсь за собственную тупость — но я не понял сокровенного смысла этой конструкции
AS>>>>> На то он и сокровенный!
AS>>>>>Зачем нужно придумывать функцию простого выделения памяти AS>>>>>чтоб потом на продолжении долгого времени успешно искать ошибку S>>>>Ну, new [] — это не простое выделение памяти, а выделение памяти под массив элементов с вызовом конструктора по умолчанию для каждого элемента массива. S>>>>delete [] соответственно вызовет деструктор для каждого элемента массива и освободит выделенную память. S>>>>Я сокровенность преобразования sA* к sA* я все-таки не понял . S>>>>Если это попытка ВНЕШНЕ (то есть для успокоения зрения )привести указатель на память под массив элементов к указателю на память под элемент, то попытка эта не только наивная, но и опасная с точки зрения утечек памяти. S>>>>И она вовсе не дает право освобождать память, выделенную new [], с помощью delete.
AS>>>Ну насколько я знаю компиляторы...они не позволяют без предупреждения оставлять попытки переопределения void* к указателю на другой тип !!!
A>>А где здесь void*?
..>> achp>> Это просто трёп? или вопрос на самом деле?
Я думаю, что вопрос. Мне тоже интересно, где тут void* нашелся
Здравствуйте Vi2, Вы писали:
Vi2>Здравствуйте CAMAD, Вы писали:
[]
Vi2>Это важно в любом случае, потому что это соответствие должно быть на уровне рефлексов! Выделил через new[], удали через delete[]. Выделил через new, удали через delete. А всю работу по оптимизации оставь компилятору — он это сделает без ошибок, в отличие от программиста!
Здравствуйте CAMAD, Вы писали:
CAMAD>Здравствуйте m.a.g., Вы писали: CAMAD>.... ...>>То ли я туплю? Все делают одну и ту же ошибку. Удалять надо так: ...>>
...>>delete[] pSA;
...>>
CAMAD>Это, конечно, важно для типов с нетривиальными деструкторами. Но для встроенных типов, например, не имеет никакого значения, каким delete удалять их массив.
Здравствуйте santucco, Вы писали:
S>Здравствуйте Alex Smirnov, Вы писали:
AS>>Здравствуйте achp, Вы писали:
A>>>Здравствуйте Alex Smirnov, Вы писали:
AS>>>>>>>> и чем народ не устраивает просто sA* p=(sA*)new sA[count]; S>>>>>>>Я дико извиняюсь за собственную тупость — но я не понял сокровенного смысла этой конструкции
AS>>>>>> На то он и сокровенный!
AS>>>>>>Зачем нужно придумывать функцию простого выделения памяти AS>>>>>>чтоб потом на продолжении долгого времени успешно искать ошибку S>>>>>Ну, new [] — это не простое выделение памяти, а выделение памяти под массив элементов с вызовом конструктора по умолчанию для каждого элемента массива. S>>>>>delete [] соответственно вызовет деструктор для каждого элемента массива и освободит выделенную память. S>>>>>Я сокровенность преобразования sA* к sA* я все-таки не понял . S>>>>>Если это попытка ВНЕШНЕ (то есть для успокоения зрения )привести указатель на память под массив элементов к указателю на память под элемент, то попытка эта не только наивная, но и опасная с точки зрения утечек памяти. S>>>>>И она вовсе не дает право освобождать память, выделенную new [], с помощью delete.
AS>>>>Ну насколько я знаю компиляторы...они не позволяют без предупреждения оставлять попытки переопределения void* к указателю на другой тип !!!
A>>>А где здесь void*?
..>>> achp>> Это просто трёп? или вопрос на самом деле? S>Я думаю, что вопрос. Мне тоже интересно, где тут void* нашелся
ДЛЯ achp и santucco популярно!!! Оператор new ВСЕГДА!!! возвращает void*
Здравствуйте achp, Вы писали:
A>Здравствуйте Alex Smirnov, Вы писали:
AS>> ДЛЯ achp и santucco популярно!!! Оператор new ВСЕГДА!!! возвращает void*
A>Новатор? A>Шутник? A>Крутой?
fchp-> неплохо было бы перечитать учебник по С++
Здравствуйте Alex Smirnov, Вы писали:
AS>Здравствуйте achp, Вы писали:
A>>Здравствуйте Alex Smirnov, Вы писали:
AS>>> ДЛЯ achp и santucco популярно!!! Оператор new ВСЕГДА!!! возвращает void*
A>>Новатор? A>>Шутник? A>>Крутой?
fchp->> неплохо было бы перечитать учебник по С++
Здравствуйте achp, Вы писали:
A>Здравствуйте Alex Smirnov, Вы писали:
AS>>Здравствуйте achp, Вы писали:
A>>>Здравствуйте Alex Smirnov, Вы писали:
AS>>>> ДЛЯ achp и santucco популярно!!! Оператор new ВСЕГДА!!! возвращает void*
A>>>Новатор? A>>>Шутник? A>>>Крутой?
fchp->>> неплохо было бы перечитать учебник по С++
A>Ну так перечитай!
achp! Повежливей надо быть!!! И не спорить о вещах в которых мало разбираешся
А Вы не пробывали организовать работу с массивом через так называемые Smart Pointers....Тогда и юзеру действительно не надо будет заботится о delete[] ???
Здравствуйте 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 *)
Народ, вы не с луны, случайно?
То, что ты привел в качестве примера — это ОПЕРАТОР new и ОПЕРАТОР delete. ОПЕРАТОР new вызываeтся ФУНКЦИЕЙ new для выделения нужного куска СЫРОЙ памяти — поэтому она и возвращает void*. Затем ФУНКЦИЯ new вызывает конструктор для полученного куска сырой памяти.
ФУНКЦИЯ delete вызывает деструктор и ОПЕРАТОР delete для освобождения памяти.
Перегружая ОПЕРАТОРЫ new и delete можно реализовать свою стратегию выделения и освобождения памяти, но они работают с СЫРОЙ памятью, поэтому используют void*.
Есть еще одна форма вызова ФУНКЦИИ new — можно передать ей указатель уже выделенный кусок памяти о она только вызовет конструктор для него
Здравствуйте 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 *)
Здравствуйте 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>См. ответ мсье Смирнову.
А ВАМ стоит посмотреть исходники!!! Там черным по белому:
void * operator new( size_t cb )
{
void *res = _nh_malloc( cb, 1 );
RTCCALLBACK(_RTC_Allocate_hook, (res, cb, 0));
return res;
}
А malloc() и её инкарнации ВСЕГДА возвращали void*. И было бы глупо возвращать что то иное!!!
Здравствуйте Алекс, Вы писали:
А>Здравствуйте Vi2, Вы писали:
Vi2>>Здравствуйте CAMAD, Вы писали:
А>[]
Vi2>>Это важно в любом случае, потому что это соответствие должно быть на уровне рефлексов! Выделил через new[], удали через delete[]. Выделил через new, удали через delete. А всю работу по оптимизации оставь компилятору — он это сделает без ошибок, в отличие от программиста!
А>довольно наивно
но верно
такие рефлексы спасают глаза от вылезания из орбит при обнаружении memory leaks
[]
S>Есть еще одна форма вызова ФУНКЦИИ new — можно передать ей указатель уже выделенный кусок памяти о она только вызовет конструктор для него
S>
S> sA* Object = new ( Buffer ) sA ( ... );
S>
Не понял. Какой конструктор может быть у уже выделенного куска памяти? Ты хочешь сказать, можно создать экземпляр какого-либо класса и при этом не вызвать конструктор?
Здравствуйте Алекс, Вы писали:
А>Здравствуйте 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[] будет жизненно важна.