Здравствуйте, Kernan, Вы писали:
K>Погоди. Это как? placement new же не меняет память, а работает поверх того что есть. Кроме того, вроде с POD точно должно быть нормально. Разве нет?
placement new инициализирует объект, в данном случае он будет default-initialized (т.к. определенного юзером конструктора очевидно нет).
Никто не гарантирует, что дефолтная инициализация сохранит то, что было в памяти до этого.
_NN>Насколько я понимаю неопределённое поведение у нас только из-за разного порядка вычисления подвыражений в "a + bar() + a".
Ты про https://timsong-cpp.github.io/cppwp/n4868/intro.execution#10.sentence-4 > If a side effect on a memory location is unsequenced relative to either another side effect on the same memory location or a value computation using the value of any object in the same memory location, and they are not potentially concurrent, the behavior is undefined
?
side effects — все в функции, а, как известно > For each function invocation F, for every evaluation A that occurs within F and every evaluation B that does not occur within F but is evaluated on the same thread and as part of the same signal handler (if any), either A is sequenced before B or B is sequenced before A.
Здравствуйте, Ip Man, Вы писали:
IM>placement new инициализирует объект, в данном случае он будет default-initialized (т.к. определенного юзером конструктора очевидно нет). IM>Никто не гарантирует, что дефолтная инициализация сохранит то, что было в памяти до этого.
Понял, надо было просто подумать получше. Если в классе A есть поле int a{0}, то при placment new этот int в 0 и уйдёт даже если конструктор дефолтный. Ну и прочее.
Почему бы просто не довести placement new до ума чтобы он не делал инициализацию? Добавить new (addr) T noctor; Придумали какие-то дикие костыли с reinterpret_cast когда всё уже было.
Здравствуйте, T4r4sB, Вы писали:
TB>Ээээ, а разве он не для того придумал, чтоб вызывать конструктор на конкретной области памяти?
Он придуман для того, чтобы создать объект на конкретной области памяти, а уж вызовет ли он конструктор или нет зависит от желания программиста. Можно, конечно, возразить задав вопрос о том, что делать с деструктором, но всё это вторично и можно тупо заставить писать тривиальные деструкторы чтобы использовать новую фишку. Короче, С++ программист понимает что хочет получить, а не как в Rust "мы ограничиваем вас borrow checker-ом потому, что вы тупой дегенерат".
Здравствуйте, T4r4sB, Вы писали:
TB>А разве это не синоним "вызвать конструктор"? TB>Просто если не вызывать конструктор, то что он должен делать-то тогда? nop?
Ты мне за семантику предъявляешь что ли?
Sic luceat lux!
Re[10]: Когда это наконец станет defined behavior?
Здравствуйте, Kernan, Вы писали:
TB>>А разве это не синоним "вызвать конструктор"? TB>>Просто если не вызывать конструктор, то что он должен делать-то тогда? nop? K>Ты мне за семантику предъявляешь что ли?
Не, для себя интересуюсь XD
Как по-твоему должен выглядеть оператор placement new не вызывающий конструктор, и какой в нём физический смысл?
Re[11]: Когда это наконец станет defined behavior?
Здравствуйте, T4r4sB, Вы писали:
TB>Как по-твоему должен выглядеть оператор placement new не вызывающий конструктор, и какой в нём физический смысл?
Так я выше сказал, размещение объекта на подготовленном куске памяти. При этом, он может и границы проверить, и типы отдать, и алайнмент правильный поюзать чтобы там не было мерзких паддингов, и даже endiannes порешать если надо. Всё это стандартным способом создания объекта. Мы просто полагаем что область памяти валидна, правильно инициализирована и т.п., а значит конструктор вызывать не надо.
Sic luceat lux!
Re[12]: Когда это наконец станет defined behavior?
Здравствуйте, Kernan, Вы писали:
K>Так я выше сказал, размещение объекта на подготовленном куске памяти. При этом, он может и границы проверить, и типы отдать, и алайнмент правильный поюзать чтобы там не было мерзких паддингов, и даже endiannes порешать если надо.
Ээээ, что-то по описанию больше похоже на десериализацию, чем на placement new, то есть абсолютно другая задача.
K>Всё это стандартным способом создания объекта. Мы просто полагаем что область памяти валидна, правильно инициализирована и т.п., а значит конструктор вызывать не надо.
Дык если в этой области памяти уже лежат правильные данные, то что такой placement new в принципе может полезного сделать?
Здравствуйте, T4r4sB, Вы писали:
TB>А разве это не синоним "вызвать конструктор"?
Нет конечно. Конструктор выполняет иницализацию, но не любая инициализация происходит с вызовом конструктора (помним про тривиальные типы, или, например, про агрегаты).
Иными словами, конструктор — это частный случай инициализации, а не общий.
Re[10]: Когда это наконец станет defined behavior?
Здравствуйте, wander, Вы писали:
W>Нет конечно. Конструктор выполняет иницализацию, но не любая инициализация происходит с вызовом конструктора (помним про тривиальные типы, или, например, про агрегаты).
Ок, в языке не хватает placement aggregate initialization. А какой ещё случай имеет смысл?
Re[11]: Когда это наконец станет defined behavior?
code review обычно не пройдёт: big-endian/little-endian S>При передаче данных на одной машине через shared memory или пайпы это не требуется.
Вряд ли для таких случаев используют Stream.
ЗЫ Я не говорю, что это совсем не нужно, может иногда понадобится для оптимизации.
code review обычно не пройдёт: big-endian/little-endian S>>При передаче данных на одной машине через shared memory или пайпы это не требуется. BFE>Вряд ли для таких случаев используют Stream.
По разному бывает.
BFE>ЗЫ Я не говорю, что это совсем не нужно, может иногда понадобится для оптимизации.
Не только. Например, некая программулина собирает и обрабатывает некоторые данные с использованием библиотек X и Y. Библиотеки большие, сложные, и не всегда работают надежно, т.е. могут падать время от времени и крашить приложение, в котором используются. Для преодоления этой проблемы приложение разбивается на процессы: N процессов посредством X и Y собирают и обрабатывают данные, результаты обработки доставляются в головной процесс через пайпы и shared memory. Если какой-то из этих N процессов падает, то его рестартуют. Тут ни про endianness не приходится задумываться, ни (по большому счету) про верификацию передаваемых между процессами данных.
Другой пример: программе нужно работать со специализированным внешним устройством через библиотеку, которая предоставлена поставщиком устройства, и которая позволяет работать с устройством только синхронно. Но это устройство имеет свойство время от времени засыпать, разбудить его можно посредством повторного вызова функции init из этой библиотеки. Однако, если устройство "уснуло" на синхронном вызове, то этот вызов не вернет назад управление даже если кто-то параллельно вызовет init. Библиотека закрытая, влезть и поправить ее нельзя. Тогда работа с устройством выносится в отдельный процесс, общение с которым идет через пайпы. Если отдельный процесс завис из-за того, что устройство в очередной раз "уснуло", то он просто убивается, и запускается новый, который вызывает init и затем успешно работает пока устройство снова уснет.
Здравствуйте, σ, Вы писали:
TB>> Оператор + левоассоциативный
σ>При чём тут это?
При том что второе сложение обязано выполниться после первого
TB>> второе сложение в любом случае выполнится после первого.
σ>А чтения из a — в любом порядке. Оба до вызова bar, оба после, или с вызовом между.
И что же гцц даже с о3 зассал один раз прочитать а и удвоить в регистре?
Ты не видишь что от порядка чтений меняется результат?