Каков полный список действий, выполняемых placement new в C ++?

StackOverflow https://stackoverflow.com/questions/1031543

  •  06-07-2019
  •  | 
  •  

Вопрос

В этот вопрос создание заводского метода, когда компилятор не поддерживает новое и размещение новое обсуждается.Очевидно, что какое-то подходящее решение могло бы быть создано с помощью malloc(), если бы все необходимые шаги были выполнены путем размещения новое воспроизводятся каким-то образом.

Что означает размещение новое делать - я попытаюсь перечислить и надеюсь ничего не пропустить - кроме следующего?

  • вызывайте конструкторы для всех базовых классов рекурсивно
  • вызовите конструкторы и инициализаторы (если таковые имеются) для всех переменных-членов
  • установите указатель vtable соответствующим образом.

Какие еще существуют действия?

Это было полезно?

Решение

Размещение new делает все регулярно new сошло бы, за исключением выделения памяти.

Я думаю, вы, по сути, поняли, что происходит, с некоторыми незначительными уточнениями:

  • очевидно, что также вызывается конструктор самого класса
  • указатели на vtable инициализируются как часть вызовов конструктора, а не отдельно.Следствием этого является то, что частично сконструированный объект (например, исключения, созданные в конструкторе) имеет свою vtable, настроенную до точки, к которой продолжалось построение.

Порядок построения / инициализации следующий:

  1. виртуальные базовые классы в порядке объявления
  2. невиртуальные базовые классы в порядке объявления
  3. члены класса в порядке объявления
  4. сам конструктор класса

Другие советы

установите указатель vtable соответствующим образом

Эта часть почти полностью определяется реализацией.Ваш компилятор может не использовать vtables.Может быть несколько указателей на vtable или один или несколько указателей на объекты, которые не являются vtables.Множественное наследование всегда интересно, как и виртуальные базовые классы.Эти метаданные не гарантированно могут быть скопированы с memcpy к другому объекту, поэтому указатель (указатели) не обязательно должен быть абсолютным.Там могут быть смещения, которые относятся к самому указателю объекта.

IIRC что обычно происходит, так это то, что вызывается конструктор базового класса, затем указатель vtable устанавливается на базовый класс, затем вызывается конструктор первого производного класса и т.д.Это делается для того, чтобы удовлетворить требованиям спецификации, касающимся того, что происходит при вызове виртуальной функции в конструкторе.Насколько я помню, в стандарте нет "списка действий", просто определенный порядок инициализации.

Таким образом, невозможно обобщить, что делает реализация, тем более что то, что у вас есть, не является реализацией стандарта C ++.Если он сокращает углы, опуская "new", по-видимому, по уважительной причине, потому что он считает, что вы не должны использовать его на целевой платформе, то кто знает, какие еще правила языка он игнорирует.Если бы можно было создать макет "new" с помощью malloc и небольшого нажатия указателя, то с какой стати компилятор просто не реализует new?Я думаю, вам нужно задавать вопросы, помеченные вашим конкретным компилятором и платформой, чтобы любые эксперты по вашему компилятору могли ответить.

Ответ @laalto в целом справедлив.Однако одно исключение подтверждает правило.

указатели на vtable инициализируются как часть вызовов конструктора, а не отдельно.

Компилятор Microsoft C ++ знает так называемые локальные vftables, т. е.vftables являются локальными для библиотеки DLL и будут клонированы для каждого импортированного класса.Это происходит потому, что компилятор хочет предоставить модифицированный деструктор, который оборачивает исходный (s.a. здесь).

Всякий раз, когда вы создаете объект импортированного класса, компилятор генерирует код, который перезаписывает исходный указатель (указатели) vftable с локальными указателями после вызова конструктора.Этот код также присутствует при размещении новых вызовов.

Существует еще одно обходное решение, помимо тех, что упомянуты в посте выше.Это обходное решение не заставляет вас изменять исходные файлы заголовков.Пожалуйста, взгляните сюда: https://godbolt.org/g/YQsffY

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top