Глобальное “размещение” удаляет []

Если Вы имеете в виду 3000 + разработчики wokring на той же кодовой базе, у меня нет подсказки. Если бы Вы означаете работать над несколькими сотнями проектов на различных местоположениях, и у Вас должен быть стандарт, я пошел бы для somethins, популярного у серьезной поддержки подключенного пользователя, т.е. не что-то затеняют, который дает Вам 10 хитов на Google.

Лично я согласился бы на SVN, я нахожусь на DEP IT с несколькими сотнями devs и предпочтительного приложения управления исходным кодом, там SVN.

:)

//W

9
задан Gwaredd 28 November 2009 в 12:27
поделиться

4 ответа

Краткий ответ:

Нет прямой поддержки для этого использования. Если вы перегружаете новый файл с другой подписью, компилятор считает это перегрузкой нового (а не размещения нового) и добавляет свой собственный код бухгалтерского учета. Нет способа (я могу найти) сказать компилятору «развернуть бухгалтерию и вызвать мою перегрузку удаления, соответствующую этой подписи» - он только вставит код, чтобы развернуть бухгалтерию при вызове void operator delete (void * p) или void operator delete [] (void * p) .

Если вы действительно переопределяете new с новой подписью, компилятор хочет, чтобы вы определяли удаление с соответствующей подписью в случае исключений во время new - это единственный раз, когда он используется.

Нет никакого удаления размещения в том смысле, что оно не вызывается, но оно определено в случае исключений (ничего не делать).

Длинный ответ:

В этой теме поднимаются некоторые интересные вопросы:

  1. Что именно void * operator new [] (size_t sz, Allocator * a) перегружает?
  2. Является ли есть или нет «размещение удаления».
  3. Как можно вызвать оператор 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) для выделения, то удаление будет по-прежнему работать как обычно.

3
ответ дан 4 December 2019 в 22:28
поделиться

В случае сомнений обратитесь к эксперту:

http://www.stroustrup.com/bs_faq2.html#placement-delete

Но как мы можем позже правильно удалить эти объекты ? Причина того, что нет встроенного «удаления размещения» для соответствия новому размещению, заключается в том, что нет общего способа гарантировать, что оно будет использоваться правильно. Ничто в системе типов C ++ не позволяет нам сделать вывод, что p1 указывает на объект, размещенный в Arena a1. Указатель на любой X, размещенный где угодно, может быть назначен p1.

В оставшейся части ссылки описано, как исправить ситуацию.

4
ответ дан 4 December 2019 в 22:28
поделиться

Вы можете посмотреть указатель вверх в своем распределителе, узнать размер из своей бухгалтерии и вычислить количество элементов, используя sizeof T.

0
ответ дан 4 December 2019 в 22:28
поделиться

] Нет такой терминологии, как «удаление размещения». Как вы сказали, если вы выделяете что-то с размещением new, то, когда придет время освободить, вам нужно вручную вызвать деструктор, а затем также позаботиться о фактическом буфере памяти, выделенном для размещения new.

Но то, что вы пытаетесь сделать, не возможно без ручного отслеживания собственных размеров распределения. Причина в том, что весь смысл «нового размещения» состоит в том, чтобы отделить выделение памяти от инициализации объекта. Таким образом, при размещении new процесс выделения буфера памяти полностью отделен от создания или разрушения любых объектов, которые могут (или не могут) когда-либо оказаться в этом буфере.

Так, например, если вы выделяете некоторый буфер, например char buf [1000] , а затем используете новое размещение для создания массива объектов Foo в этом буфере, где C ++ должен хранить информацию о размере массива? Он не будет хранить его в вашем буфере, потому что не знает, что вы хотите делать с этим буфером. Так что вы должны записывать размер каждого выделения, а затем правильно связывать его с освобождением.

1
ответ дан 4 December 2019 в 22:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: