Если Вы имеете в виду 3000 + разработчики wokring на той же кодовой базе, у меня нет подсказки. Если бы Вы означаете работать над несколькими сотнями проектов на различных местоположениях, и у Вас должен быть стандарт, я пошел бы для somethins, популярного у серьезной поддержки подключенного пользователя, т.е. не что-то затеняют, который дает Вам 10 хитов на Google.
Лично я согласился бы на SVN, я нахожусь на DEP IT с несколькими сотнями devs и предпочтительного приложения управления исходным кодом, там SVN.
:)
//W
Краткий ответ:
Нет прямой поддержки для этого использования. Если вы перегружаете новый файл с другой подписью, компилятор считает это перегрузкой нового (а не размещения нового) и добавляет свой собственный код бухгалтерского учета. Нет способа (я могу найти) сказать компилятору «развернуть бухгалтерию и вызвать мою перегрузку удаления, соответствующую этой подписи» - он только вставит код, чтобы развернуть бухгалтерию при вызове void operator delete (void * p)
или void operator delete [] (void * p)
.
Если вы действительно переопределяете new с новой подписью, компилятор хочет, чтобы вы определяли удаление с соответствующей подписью в случае исключений во время new - это единственный раз, когда он используется.
Нет никакого удаления размещения в том смысле, что оно не вызывается, но оно определено в случае исключений (ничего не делать).
Длинный ответ:
В этой теме поднимаются некоторые интересные вопросы:
void * operator new [] (size_t sz, Allocator * a)
перегружает? оператор void delete [] (void * p, Allocator * a)
таким образом, чтобы компилятор вставлял его завершение бухгалтерского учета? Пункт 1: Много разговоров о перегрузке размещения новых. Учитывая, что компилятор вставляет бухгалтерский код, он должен придерживаться мнения, что этот void * operator new [] (size_t sz, Allocator * a)
объявляет перегрузку (без размещения) new. Он никогда не будет вставлять бухгалтерский код для размещения new, потому что точка размещения new заключается в том, что вы обрабатываете его сами.
Пункт 2: RE "Нет такой вещи, как удаление размещения", вы найдете что-то ужасно похожее (и прокомментированное как таковое), например, в новом заголовке VS2k8. Это просто заглушка, используемая в случаях, когда во время размещения new. Однако кажется правдой, что вы не можете активировать удаление размещения значимым образом.
Пункт 3: Если есть способ, я не могу его найти. В этом суть проблемы.
С точки зрения практического решения проблемы, это кажется провалом.
например:
//intention: user provides memory pool, compiler works out how many bytes required
//and does its own book-keeping, as it would for a void* operator new[](size_t sz) overload
//calling syntax: CObj* pMyArr = new(pMyMemPool) CObj[20];
void* operator new[](size_t sz, IAlloc* pMemPool)
{ return pMemPool->alloc(sz); }
//problem: don't know the syntax to call this!
//e.g. delete[](pMyMemPool) pMyArr is syntax error
void* operator delete[](void* p, IAlloc* pMemPool)
{ return pMemPool->free(p); }
//nb: can be called as operator delete(pMyArr, pMyMemPool);
//but compiler does not finish its book-keeping or call dtors for you in that case.
Обратите внимание, что эта асимметрия существует и для новых и удаленных без массива. Однако, поскольку (эмпирически) рассматриваемый компилятор не ведет дополнительного учета, все это можно заставить работать. Опять же, если это закреплено в стандарте, я не знаю.
void* operator new(size_t sz, IAlloc* pMemPool)
{ return pMemPool->alloc(sz); }
//don't know syntax to get this called by compiler!
void operator delete(void* p, IAlloc* pMemPool)
{ pMemPool->free(p); }
//is ok though, can work around
template<class T> void tdelete(void* p, IAlloc* pMemPool)
{
//no problems, p points straight at object
p->~T();
operator delete(p, pMemPool);
//OR just
pMemPool->free(p);
}
void* operator new[](size_t sz, IAlloc* pMemPool)
{ return pMemPool->alloc(sz); }
//again, don't know syntax to end up here.
void operator delete[](void* p, IAlloc* pMemPool)
{ pMemPool->free(p); }
//can't work around this time!
template<class T> void tarrdelete(void* p, IAlloc* pMemPool)
{
//problem 1: how many to dtor?
for(int i=0; i<???; ++i)
{ reinterpret_cast<T*>(p+i)->~T(); }
//problem 2: p points at first element in array. this is not always the address
//that was allocated originally.
pMemPool->free(?);
//as already explained by OP, no way to tell if p is address allocated or
//address allocated+4 bytes, or something else altogether. this means no way to know what address to un-alloc or how many dtors to call.
}
Наконец, я изложу obvs. - перегрузки без расширенного списка параметров работают:
//sz may include extra for book-keeping
void* operator new[](size_t sz)
{ return GAlloc->alloc(sz); }
//works fine, compiler handled book-keeping and p is the pointer you allocated
void operator delete[](void* p)
{ return GAlloc->free(p); }
Сводка : Есть ли синтаксис, который позволит вызывать перегрузку delete с расширенным списком параметров с включенной "магией" компилятора. Или есть способ добавить параметры к размещению new путем переопределения?
Подозреваемый ответ : Нет.
Следствие : Вы не можете отклониться от 6 встроенных новых подписей с полной свободой. Это приводит к перегрузке новых, с бухгалтерией, генерируемой компилятором, но нет доступа к соответствующему удалению, чтобы расслабиться в бухгалтерии.
Предостережение : вы можете отклониться от встроенных подписей, но только чтобы ввести код, который вам не нужно снова обрабатывать при удалении (например, инструментарий). Если вы перейдете к версии void * operator new (size_t s)
для выделения, то удаление будет по-прежнему работать как обычно.
В случае сомнений обратитесь к эксперту:
http://www.stroustrup.com/bs_faq2.html#placement-delete
Но как мы можем позже правильно удалить эти объекты ? Причина того, что нет встроенного «удаления размещения» для соответствия новому размещению, заключается в том, что нет общего способа гарантировать, что оно будет использоваться правильно. Ничто в системе типов C ++ не позволяет нам сделать вывод, что p1 указывает на объект, размещенный в Arena a1. Указатель на любой X, размещенный где угодно, может быть назначен p1.
В оставшейся части ссылки описано, как исправить ситуацию.
Вы можете посмотреть указатель вверх в своем распределителе, узнать размер из своей бухгалтерии и вычислить количество элементов, используя sizeof T.
] Нет такой терминологии, как «удаление размещения». Как вы сказали, если вы выделяете что-то с размещением new, то, когда придет время освободить, вам нужно вручную вызвать деструктор, а затем также позаботиться о фактическом буфере памяти, выделенном для размещения new.
Но то, что вы пытаетесь сделать, не возможно без ручного отслеживания собственных размеров распределения. Причина в том, что весь смысл «нового размещения» состоит в том, чтобы отделить выделение памяти от инициализации объекта. Таким образом, при размещении new процесс выделения буфера памяти полностью отделен от создания или разрушения любых объектов, которые могут (или не могут) когда-либо оказаться в этом буфере.
Так, например, если вы выделяете некоторый буфер, например char buf [1000]
, а затем используете новое размещение для создания массива объектов Foo
в этом буфере, где C ++ должен хранить информацию о размере массива? Он не будет хранить его в вашем буфере, потому что не знает, что вы хотите делать с этим буфером. Так что вы должны записывать размер каждого выделения, а затем правильно связывать его с освобождением.