Либо так
template < typename T >
void func()
{
...
}
и вызывай
func < T > ()
либо можно извратиться так
template < typename T >
void func1(T * )
{
...
}
#define func(T) func1((T*)0)
вызвать так
func(double)
>А в чём смысл данной операции? Это же эквивалентно вызову дефолтного "new T".
Нужно следить за использованием динамической памяти, главным образом для отлова утечек. При использовании голого malloc как я понял возникает проблема с виртуальными функциями, но надеюсь она мне не помешает.
>Нужно следить за использованием динамической памяти, главным образом
>для отлова утечек. При использовании голого malloc как я понял
>возникает проблема с виртуальными функциями, но надеюсь она мне не
>помешает.
template<class T>
T* allocate_and_construct(T*)
{
void* p = malloc( sizeof( T ) );
return new( p )T();
}
template<class T>
void destruct_and_deallocate(T* t)
{
t->~T();
free( t );
}
и дальше можно делать вот так:
A* p;
A* a = allocate_and_construct( p );
destruct_and_deallocate( a );
> template<class T>
> T* allocate_and_construct(T*)
> {
> void* p = malloc( sizeof( T ) );
> return new( p )T();
> }
-1
В конструкторе может кинуться исключение, память никто не вернет.
> При использовании голого malloc как я понял возникает проблема с виртуальными функциями
malloc используется для выделения памяти, заполнение vtable происходит в момент конструирования объекта
> О ужас! Кошмар! Придется использовать try, catch и throw
Твоя ирония здесь не уместна, приведенный тобой код потенциально опасен.
> Это совсем невозможно пережить?
Нет. Сразу об стену.
>malloc используется для выделения памяти, заполнение vtable происходит в момент конструирования объекта
На счет malloc тоже возникает большой вопрос. При использовании new конструирование объекта происходит автоматически после выделения памяти для его хранения. Но при использовании моей версии new (только malloc) конструктор все равно вызывается. Например, следующий код:
new это оператор, который вызывает функцию operator new для выделения памяти под объект, затем вызывает конструктор. Переопределить можно только функцию operator new. Оператор new переопределить невозможно, так как это оператор а не функция. Вот такой вот каламбур :)
> Нужно следить за использованием динамической памяти, главным образом
> для отлова утечек. При использовании голого malloc как я понял
> возникает проблема с виртуальными функциями, но надеюсь она мне не
> помешает.
Как я понял - товарищ хочет изобрести механизм управления памятью через реализацию какого-то своего мегашаблона. Если у тебя есть другое понимание - поделись пожалуйста.
>Как я понял - товарищ хочет изобрести механизм управления памятью через реализацию какого-то своего мегашаблона. Если у тебя есть другое понимание - поделись пожалуйста.
На самом деле мне нужно уметь находить утечки. В перспективе, возможно понадобится ручное управление кучей (если не будет устраивать производительность), если это возможно, но пока что ограничусь стандартными средствами C++.
Если утечки нужно находить при написании - то пользуйся чем и все - valgrind. Хороший инструмент. Если нужно во время работы.. ты планируешь их много оставлять для runtime'а? Может быть лучше тогда взять язык с gc?
>>> Лушче посмотри на auto_ptr из STL и разные ptr'ы из boost
>> Лучше посмотреть на Boehm's GC.
> Он умеет вызывать деструкторы? O_O
да, но не всегда :) посмотри /usr/include/gc/gc_cpp.h:
A collectable object may have a clean-up function, which will be
invoked when the collector discovers the object to be inaccessible.
An object derived from "gc_cleanup" or containing a member derived
from "gc_cleanup" has a default clean-up function that invokes the
object's destructors. Explicit clean-up functions may be specified as
an additional placement argument:
>На самом деле мне нужно уметь находить утечки. В перспективе, >возможно понадобится ручное управление кучей (если не будет >устраивать производительность), если это возможно, но пока что >ограничусь стандартными средствами C++.
1)(один)
У меня была аналогичная проблема (VC++). Советую дописать дефолтный макрос DEBUG_NEW, если ты в вижуалсях. Я так и сделал(деталей, извини, не помню). На других компиляторах и идЭешниках , кстати, скорее всего есть аналогичные инструменты. Если в твоём нема, см. вижуалсишный DEBUG_NEW и делай свой по образу и подобию.
2)(два)
Может и не в тему, конечно, но... Не советую переопределять new создающий, который для объектов класса, ИМХО жуткий гемор. Почитай теорию (Страуструп, Мейерс и т.д.). там сказано, что для энтого гемора, следует переопределить целый КОМПЛЕКС: new канонический throw std::bad_alloc, new размещающий, new nothrow и delete. Вроде так. Причём если перегрузил один из вышеуказанных, будь добёр и остальные иначе быть попе.
3)(три)
Советую также, подумать, а насколько опасна тебе эта самая утечка. Например, в виндах, KDE, других user-time ситемах очень часто на утечку памяти моно забить, т.к. там на 2-ом уровне ядра живёт бог (или баг) по имени "МЕнеджер памяти", который с удовольствием разгребёт твой мусор. Это ещё вопрос, что считать утечкой.
4)(чтыре)
Если же ты действительно провёл все необходимые тесты своих структур данных и они однозначно указывают на необходимость динамического освобождения динамически выделенной памяти, подумай об использовании патерна boost::shared_ptr( вроде я видел такой свет в этом топике? ).
Если boost::shared_ptr реально снижает эффекимвность, рассмотри Loki::smart_ptr
5)(пять)
"Перспектива ручного управления кучей" - это ... ЭЭЭЭ ... ну очень говёная перспектива. Хуже перспективы не придумаешь. Советую крепко подумать, как этого избежать. Дело в том, что я имею грёбаный опыт создания ручных MemoryPool-ов для "no-systemd"-контроллеров на базе C51 и AVR-Risc. Это были приложения для различных "переходников" типа южного/северного мостов в маме-плате. Так вот, там НУЖНО было создавать объекты динамически, но НИКАКИЕ языковые средства для этого не подходили по вполне понятным причинам. Ни тебе маллок, ни нью. Ты прсто не представляешь, сколько граблей было перелопачено.. Вывод: НЕ СТОИТ УПРАВЛЯТЬ КУЧЕЙ ВРУЧНУЮ.
И ещё вот что. В библиотеке Loki есть феноменально-замечательный, платформенно-независимый, полностью соответсвующий стандарту c++, менеджер памяти для малых объектов. Использую эту прелесть в соих прогах - эффективность сильно улучшится.
>Лушче посмотри на auto_ptr из STL и разные ptr'ы из boost
Вощета std::auto_ptr функционально ограниченн своей семантикой разрушающего копирования. Например, его нельзя в контейнерах хранить.
boost::shred_ptr<T> - это хорошо, пока тебя
1.не волнует эффективность работы с кучей
2.ты не планируешь юзать объекты класса Т в многопоточных приложениях.
Насколько я понял, 1) - актуально для автора топика. В будущем возможно понадобится и 2). Чтобы раз и навсегда решить эти проблемы, рискну посоветовать подумать о применеии Loki::SmartPtr. Там, как я уже говорил, есть Small Oject Fixed Allocator, а обёекты класса T, скорее всего имеют малый размер.