Будет ли законным объединение необработанных операторов, размещение новых и стандартное удаление? - PullRequest
5 голосов
/ 10 июля 2011

ребята! Из любопытства - следующий код, вероятно, не будет законным, не так ли?

T *p = ::operator new(sizeof(T)); // allocate memory for a T
new (p) T; // construct a T into the allocated memory
delete p; //delete the object using the standard delete operator

Ответы [ 3 ]

7 голосов
/ 10 июля 2011

Нет. Вы можете delete получить только то, что получите от new - без исключений.

1 голос
/ 10 июля 2011

Есть по крайней мере одно обстоятельство, в котором оно явно не определено: если вы перегрузили operator new и operator delete для T, то это попытается выделить память с помощью ::operator new, но удалить ее с помощью T::operator delete,Если ваш T::operator delete не является просто оберткой вокруг ::operator delete, это вызовет проблему.

Кроме этого, я думаю, что это, вероятно, определено.Стандарт очень конкретен в отношении того факта, что new expression выделяет свою память, используя функцию выделения (§5.3.4 / 10), которая будет ::operator new, если вы не предоставили T::operator new.

Ваше новое выражение размещения затем инициализирует объект, как описано для нового выражения в первой точке маркера в §5.3.4 / 15.

Затем мы переходим к стороне уничтожения.Согласно $ 5.3.5 / 1: «Оператор delete-expression уничтожает наиболее производный объект (1.8) или массив, созданный новым выражением».Это требует, чтобы вы использовали новое выражение для создания объекта - который у вас есть.Вы использовали размещение new, которое является одной из возможностей для нового выражения и указано в §5.3.4 / 1.

Следующие применимые требования выглядят следующим образом: «Операнд должен иметьтип указателя или тип класса, имеющий единственную функцию преобразования (12.3.2) в тип указателя. "Опять же, ваше выражение также соответствует этому.

Я собираюсь процитировать больше требований без дальнейших комментариев, за исключением того, что ваш код, кажется, соответствует всем им (некоторые ограничивают реализацию выражения удаления, а неуказатель, который вы можете использовать в одном):

  • (§5.3.5 / 2): «В первом варианте (объект удаления) значением операнда удаления должен быть указательна объект, не являющийся массивом, или указатель на подобъект (1.8), представляющий базовый класс такого объекта (раздел 10). Если нет, поведение не определено. "

  • (§5.3.5 / 3): «В первом альтернативном варианте (удаление объекта), если статический тип операнда отличается от его динамического типа, статический тип должен быть базовым классом динамического типа операнда и статическогоТип должен иметь виртуальный деструктор или поведение не определено.

  • (§5.3.5 / 4): «В первом варианте (удаление объекта), если статический тип операндаотличается от своего динамического типа,Тип tic должен быть базовым классом динамического типа операнда, а статический тип должен иметь виртуальный деструктор или поведение не определено. "

  • (§5.3.5 / 6):"Выражение удаления вызовет деструктор (если он есть) для объекта или элементов удаляемого массива. "

  • (§5.3.5 / 7): выражение удалениявызовет функцию освобождения (3.7.3.2).

С начальным предупреждением о ::operator new против T::operator new, я думаю, указатель, который вы используете в delete expressionотвечает всем требованиям, поэтому поведение должно быть определено.

Сказав все это, я, конечно, надеюсь это чисто академический интерес - хотя мне кажется, что код действительноопределенное поведение, это паршивая идея даже в лучшем случае.

0 голосов
/ 10 июля 2011

Если исходить из правильного утверждения DeadMG, нет проблем с небольшим изменением вашего кода:

unsigned char* addr = new unsigned char[sizeof(MySimpleStructure)];
MySimpleStructure* p = new (addr) MySimpleStructure;
delete [] addr;

Поскольку мы delete ing addr, которые были возвращены new, нет никаких проблем с тем, что это законно. Конечно, после удаления addr доступ к p не должен быть доступным (это висящий указатель в то время). Также обратите внимание, что для MySimpleStructure, выделенного для размещения, нового для p, не будет вызываться его деструктор.

...