Сообщение Re[4]: ::operator new() в самописном стэке от 10.06.2023 18:53
Изменено 10.06.2023 18:55 Sm0ke
Re[4]: ::operator new() в самописном стэке
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, Sm0ke, Вы писали:
S>>
R>Вообще, этот фрагмент настораживает. Здесь ты выполняешь преобразование указаетля на просто кусок памяти к указателю на объект, что небезопасно в общем случае. Если Т — это нетривиально конструируемый тип, то время жизни объекта в этой точке еще не началось и любая попытка обращения к этому объекту порождает неопределенное поведение. Использовать данный кусок памяти как объект типа Т можно будет только после выполнения placement new. Но в таком случае и никаких преобразований не понадобится, ибо placement new сразу возвратит указатель нужного типа.
placement new будет в методе emplace_back(). А при m_count == 0 не должно быть обращений к непроинициализированной памяти.
Конструктор лишь резервирует память под массив. Создание объектов там будет по требованию.
Исходник этого вектора на гитхабе (в процессе написания):
https://github.com/deemetrius/ksi/blob/main/ksi/src_just/just.vector.ixx
Вот вопрос: как лучше написать метод insert(), emplace() чтобы было exception safety? Если конструктор элемента кинет исключение.
Вариант 1: Раздвигать последующие элементы, placement new, ловить исключение (сдвигать обратно и рефровать), обновлять count когда нет исключения.
Вариант 2: В отдельном месте placement new, потом memcpy в раздвинутое место массива.
Вариант 3: ...
R>Здравствуйте, Sm0ke, Вы писали:
S>>
S>>return reinterpret_cast<pointer>(
S>> ::operator new(s_size * p_reserve, s_align, std::nothrow)
S>>);
S>>R>Вообще, этот фрагмент настораживает. Здесь ты выполняешь преобразование указаетля на просто кусок памяти к указателю на объект, что небезопасно в общем случае. Если Т — это нетривиально конструируемый тип, то время жизни объекта в этой точке еще не началось и любая попытка обращения к этому объекту порождает неопределенное поведение. Использовать данный кусок памяти как объект типа Т можно будет только после выполнения placement new. Но в таком случае и никаких преобразований не понадобится, ибо placement new сразу возвратит указатель нужного типа.
placement new будет в методе emplace_back(). А при m_count == 0 не должно быть обращений к непроинициализированной памяти.
Конструктор лишь резервирует память под массив. Создание объектов там будет по требованию.
Исходник этого вектора на гитхабе (в процессе написания):
https://github.com/deemetrius/ksi/blob/main/ksi/src_just/just.vector.ixx
Вот вопрос: как лучше написать метод insert(), emplace() чтобы было exception safety? Если конструктор элемента кинет исключение.
Вариант 1: Раздвигать последующие элементы, placement new, ловить исключение (сдвигать обратно и рефровать), обновлять count когда нет исключения.
Вариант 2: В отдельном месте placement new, потом memcpy в раздвинутое место массива.
Вариант 3: ...
Re[4]: ::operator new() в самописном стэке
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, Sm0ke, Вы писали:
S>>
R>Вообще, этот фрагмент настораживает. Здесь ты выполняешь преобразование указаетля на просто кусок памяти к указателю на объект, что небезопасно в общем случае. Если Т — это нетривиально конструируемый тип, то время жизни объекта в этой точке еще не началось и любая попытка обращения к этому объекту порождает неопределенное поведение. Использовать данный кусок памяти как объект типа Т можно будет только после выполнения placement new. Но в таком случае и никаких преобразований не понадобится, ибо placement new сразу возвратит указатель нужного типа.
placement new будет в методе emplace_back(). А при m_count == 0 не должно быть обращений к непроинициализированной памяти.
Конструктор лишь резервирует память под массив. Создание объектов там будет по требованию.
Исходник этого вектора на гитхабе (в процессе написания):
https://github.com/deemetrius/ksi/blob/main/ksi/src_just/just.vector.ixx
Вот вопрос: как лучше написать метод insert(), emplace() чтобы было exception safety? Если конструктор элемента кинет исключение.
Вариант 1: Раздвигать последующие элементы, placement new, ловить исключение (сдвигать обратно и рефровать), обновлять count когда нет исключения.
Вариант 2: В отдельном месте placement new, потом memcpy в раздвинутое место массива.
Вариант 3: ...
В варианте 1 возможно изменение capacity даже при исключении. В варианте 2 при исключении capacity прежнее.
R>Здравствуйте, Sm0ke, Вы писали:
S>>
S>>return reinterpret_cast<pointer>(
S>> ::operator new(s_size * p_reserve, s_align, std::nothrow)
S>>);
S>>R>Вообще, этот фрагмент настораживает. Здесь ты выполняешь преобразование указаетля на просто кусок памяти к указателю на объект, что небезопасно в общем случае. Если Т — это нетривиально конструируемый тип, то время жизни объекта в этой точке еще не началось и любая попытка обращения к этому объекту порождает неопределенное поведение. Использовать данный кусок памяти как объект типа Т можно будет только после выполнения placement new. Но в таком случае и никаких преобразований не понадобится, ибо placement new сразу возвратит указатель нужного типа.
placement new будет в методе emplace_back(). А при m_count == 0 не должно быть обращений к непроинициализированной памяти.
Конструктор лишь резервирует память под массив. Создание объектов там будет по требованию.
Исходник этого вектора на гитхабе (в процессе написания):
https://github.com/deemetrius/ksi/blob/main/ksi/src_just/just.vector.ixx
Вот вопрос: как лучше написать метод insert(), emplace() чтобы было exception safety? Если конструктор элемента кинет исключение.
Вариант 1: Раздвигать последующие элементы, placement new, ловить исключение (сдвигать обратно и рефровать), обновлять count когда нет исключения.
Вариант 2: В отдельном месте placement new, потом memcpy в раздвинутое место массива.
Вариант 3: ...
В варианте 1 возможно изменение capacity даже при исключении. В варианте 2 при исключении capacity прежнее.