Этот вопрос очень интересный.Это правда, что формулировка о продолжительности динамического хранения и выражениях new
не исключает размещение нового.
Неоднозначность в формулировке обусловлена большим разнообразием случаев, которые необходимо охватить:
int main()
{
struct Simple { int i; } s { 42 };
new (&s.i) int { 43 }; // the lifecyle of the newly created object
// will auto, since Simple will be destroyed when
// going out of scope
struct Complex { char s[256]; } c;
Simple *p = new (&c.s) Simple; // the lifecycle of the newly created object
// is dynamic. You'll need to delete it in time.
// because compiler doesn't know about its true nature
// and memory will be lost when going out of scope
}
Стандарт, к счастью, достаточно точен, так что если вы предоставите правильный код (т.е. нет UB), каждый компилятор будет выдавать один и тот же результат.
Фактически, динамическое создание объекта (размещение нового) не обязательно означает, что жизненный цикл объекта не зависит от области, в которой создается объект.Но это зависит от вас, чтобы убедиться, что объект будет уничтожен в должное время, и, следовательно, это рассматривается как динамическая продолжительность хранения.
Ключевым моментом здесь является распределение.Только выделение памяти может сделать продолжительность объекта действительно независимой от области, в которой он был создан.Это выражено в стандарте, но, возможно, не так ясно, как могло бы быть.Давайте начнем с полного предложения в basic.stc / 2 :
Статическое, потоковое и автоматическое хранение связано с объектами , представленными объявлениями и неявно созданными с помощьюреализация .Динамическая продолжительность хранения связана с объектами, созданными новым выражением.
Здесь я понимаю, что последнее предложение применяется только в том случае, если объект еще не охватывается первым предложением.Но это личная интерпретация на данный момент.Так что единственное, что можно сказать наверняка, это то, что в случае совпадения требуется дополнительная осторожность.
Итак, давайте более подробно рассмотрим Продолжительность динамического хранения [basic.stc.dynamic] / 1
Объекты могут создаваться динамически во время выполнения программы (...).Реализация C ++ обеспечивает доступ к динамическому хранилищу и управление им через оператор глобальных распределений , оператор new и оператор new [], а также оператор удаления глобальных функций удаления и оператор удаления [].[ Примечание: формы невыделения, описанные в 21.6.2.3, не выполняют распределение или освобождение.- примечание конца ]
Во втором предложении ясно, что динамическое хранение означает выделение.Затем следует интересное примечание, которое относится именно к главе [new.delete.placement] / 1 :
Эти функции зарезервированы;программа C ++ может не определять функции, которые заменяют версии в стандартной библиотеке C ++. Положения пункта 6.7.4 не применяются к этим зарезервированным формам размещения операторов new и operator delete.
Раздел 6.7.4 - это раздел basic.stc.dynamic .Это означает, что специальное распределение, используемое для размещения новых, не создает динамическое хранилище.
Тот факт, что динамическое хранилище и длительность динамического хранилища не являются одним и тем же, затрудняет выражение всего материала:
- длительность динамического хранения означает, что вы должны позаботиться ожизненный цикл объекта и удаление при необходимости
- динамического хранилища означает, что нет никаких ограничений на продолжительность хранения.
- Создание объекта продолжительности динамического хранения в другом месте, чем в динамическом хранилище (и особенно в месте автоматического хранения), требует особой осторожности, так как вы должны убедиться, что он уничтожен, пока хранилище доступно.Если вы просто замените объект объектом того же типа в новом месте размещения, вы получите выгоду от кода, который уничтожит объект при выходе из области видимости.Но в любом другом случае вам нужно позаботиться.
Здесь онлайн-демонстрация , чтобы поиграть с новым размещением и разрушением, а также посмотреть, что происходит, когда окружающий объект выходит из области видимости.Он использует класс Tracer
, который будет выделять лучше, чем int
различные случаи (включая удаление предыдущего объекта перед вызовом нового размещения).
Заключение: Я думаю, что нельзя избежать некоторой двусмысленности и округлости ни в одном стандарте с такой длинной историей и с таким большим количеством участников.Но в этом случае вы можете видеть, что сам вопрос имеет больше аспектов, чем вы ожидали в первую очередь.