Тут смотрю Mock-интервью по плюсам, в одном из них попросили написать человека класс vector. Заинтересовал подход для реализации метода resize, у них он называется "подход с vector_base", с 57:10 про него говорят. Это про то, как обрабатывать ситуацию, когда во время resize удалось выделить новый буфер под данные, но при копировании в него какой-то конструктор копирования бросил исключение и теперь, для всех скопированных элементов надо вызвать деструктор. Никто не сталкивался с таким? И еще вопрос, как вам факт использования try/catch в классе вектора, не режет глаз? Нельзя ли без него как-то обойтись (видимо надо будет использовать RAII обертку)?
Здравствуйте, Максим, Вы писали:
М>Тут смотрю Mock-интервью по плюсам, в одном из них попросили написать человека класс vector. Заинтересовал подход для реализации метода resize, у них он называется "подход с vector_base", с 57:10 про него говорят. Это про то, как обрабатывать ситуацию, когда во время resize удалось выделить новый буфер под данные, но при копировании в него какой-то конструктор копирования бросил исключение и теперь, для всех скопированных элементов надо вызвать деструктор. Никто не сталкивался с таким? И еще вопрос, как вам факт использования try/catch в классе вектора, не режет глаз? Нельзя ли без него как-то обойтись (видимо надо будет использовать RAII обертку)?
М>https://youtu.be/n5ddGADQIqY?t=3431
Если через конструктор копирования, то можно и через обёртку (без try).
В теле функции объявляем новый вектор. Пошагово копируем и увеличиваем count. При исключении новый вектор удалит только скопированные объекты с валидным count.
Если исключения нет, то:
Потом свапаем impl с this. Новый вектор со старым буфером удалится при выходе из функции как обычная локальная переменная.
А если move конструкторы, то как? Не мувать же их обратно... Или move конструктор элементов должен быть noexcept.
Здравствуйте, Максим, Вы писали:
М>Тут смотрю Mock-интервью по плюсам, в одном из них попросили написать человека класс vector. Заинтересовал подход для реализации метода resize
меня больше удивило, что этот подход используется в стандартных реализациях.
Разве что-то типа такого будет оверхедом?
Здравствуйте, Максим, Вы писали:
М>Тут смотрю Mock-интервью по плюсам, в одном из них попросили написать человека класс vector. Заинтересовал подход для реализации метода resize, у них он называется "подход с vector_base", с 57:10 про него говорят. Это про то, как обрабатывать ситуацию, когда во время resize удалось выделить новый буфер под данные, но при копировании в него какой-то конструктор копирования бросил исключение и теперь, для всех скопированных элементов надо вызвать деструктор. Никто не сталкивался с таким? И еще вопрос, как вам факт использования try/catch в классе вектора, не режет глаз? Нельзя ли без него как-то обойтись (видимо надо будет использовать RAII обертку)?
Самое дикое, что для всех когда-либо реально используемых мной классов достаточно тупо побитового копирования с удалением старого блока без вызова деструкторов. С++ переусложняет ситуацию на ровном месте
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, Sm0ke, Вы писали:
S> Или move конструктор элементов должен быть noexcept.
Как он может быть НЕ noexcept? Не, я в курсе, что конструкции языка такое допускают. Но как такое на практике вообще блин возможно? И как оно должно отрабатывать при исключении?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
TB>Здравствуйте, Максим, Вы писали:
М>>Тут смотрю Mock-интервью по плюсам, в одном из них попросили написать человека класс vector. Заинтересовал подход для реализации метода resize, у них он называется "подход с vector_base", с 57:10 про него говорят. Это про то, как обрабатывать ситуацию, когда во время resize удалось выделить новый буфер под данные, но при копировании в него какой-то конструктор копирования бросил исключение и теперь, для всех скопированных элементов надо вызвать деструктор. Никто не сталкивался с таким? И еще вопрос, как вам факт использования try/catch в классе вектора, не режет глаз? Нельзя ли без него как-то обойтись (видимо надо будет использовать RAII обертку)?
TB>Самое дикое, что для всех когда-либо реально используемых мной классов достаточно тупо побитового копирования с удалением старого блока без вызова деструкторов. С++ переусложняет ситуацию на ровном месте
Вот по этому люди и велосипедят собственные векторы со своим способом копирования переноса элементов))
Здравствуйте, T4r4sB, Вы писали:
М>>Тут смотрю Mock-интервью по плюсам, в одном из них попросили написать человека класс vector. Заинтересовал подход для реализации метода resize, у них он называется "подход с vector_base", с 57:10 про него говорят. Это про то, как обрабатывать ситуацию, когда во время resize удалось выделить новый буфер под данные, но при копировании в него какой-то конструктор копирования бросил исключение и теперь, для всех скопированных элементов надо вызвать деструктор. Никто не сталкивался с таким? И еще вопрос, как вам факт использования try/catch в классе вектора, не режет глаз? Нельзя ли без него как-то обойтись (видимо надо будет использовать RAII обертку)?
TB>Самое дикое, что для всех когда-либо реально используемых мной классов достаточно тупо побитового копирования с удалением старого блока без вызова деструкторов. С++ переусложняет ситуацию на ровном месте
Как понять побитового копирования? А если класс вида class C { char data[16]; char *data_ptr; };, где data_ptr это указатель на один из элементов data?
Здравствуйте, vsb, Вы писали:
vsb> А если класс вида class C { char data[16]; char *data_ptr; };, где data_ptr это указатель на один из элементов data?
Ты реально таким штукам прописываешь мув-конструктор? Или просто стараешься не гонять по памяти? Типа хранить в юнике на крайнях и всё такое.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, vsb, Вы писали:
vsb>Как понять побитового копирования? А если класс вида class C { char data[16]; char *data_ptr; };, где data_ptr это указатель на один из элементов data?
Ну если не использовать указатели, перейти на индексы, в массивах хранить POD'ы, то получается запросто.
При правильном применении этот подход даёт ощутимые ништяки.
Но такие структуры применимы не везде.
_____________________
С уважением,
Stanislav V. Zudin
Здравствуйте, T4r4sB, Вы писали:
TB>Самое дикое, что для всех когда-либо реально используемых мной классов достаточно тупо побитового копирования с удалением старого блока без вызова деструкторов. С++ переусложняет ситуацию на ровном месте
Что он переусложняет-то? Он наоборот упрощает. Тебе не нужно думать об этом. Если класс trivially copyable, то: string, vector или любой другой последовательный контейнер, сам будет использовать memcpy и memmove.
S>А если move конструкторы, то как? Не мувать же их обратно... Или move конструктор элементов должен быть noexcept.
У меня аналогичный вопрос возник...
Можно в теории проверять во время компиляции есть ли у оператора перемещения директива noexcept и если есть, то делать move, а иначе копировать. Но выглядит как-то сложновато.
Здравствуйте, T4r4sB, Вы писали:
TB>Самое дикое, что для всех когда-либо реально используемых мной классов достаточно тупо побитового копирования с удалением старого блока без вызова деструкторов. С++ переусложняет ситуацию на ровном месте
Вроде как есть (должны быть) специализации операций над вектором с упрощённой логикой для таких типов.
Здравствуйте, flаt, Вы писали:
F>Вроде как есть (должны быть) специализации операций над вектором с упрощённой логикой для таких типов.
Для каких таких? Для строк, юников, деревьев, хеш-таблиц, других векторов — всех их можно побитово копировать. Но вместо этого делается поэлементный мув. Когда изобретут такую оптимизацию?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
TB>Здравствуйте, Sm0ke, Вы писали:
S>> Или move конструктор элементов должен быть noexcept.
TB>Как он может быть НЕ noexcept? Не, я в курсе, что конструкции языка такое допускают. Но как такое на практике вообще блин возможно? И как оно должно отрабатывать при исключении?
что здесь удивительного? Разработчик забыл поставить noexcept и получил копирование в векторе. Всё в стиле C++: не доглядел — отстрелил ногу.
Здравствуйте, sergii.p, Вы писали:
SP>что здесь удивительного? Разработчик забыл поставить noexcept и получил копирование в векторе. Всё в стиле C++: не доглядел — отстрелил ногу.
Ну почему отстрелил? Просто не произвёл тонкую настройку .
Здравствуйте, T4r4sB, Вы писали:
TB>Вектор, строка, юник не являются тривиально_копиабельными. Но для них тоже можно делать memcpy и memmove. Ну и где?!
Что где?! Напиши нормально что ты имеешь в виду. Внутри себя вектор, строка и т.д. и так будут использовать memcpy и memmove, если тип их значения тривиально копируемый. Если ты имеешь в виду вектор векторов, то какой там memcpy
Здравствуйте, Videoman, Вы писали:
V>Здравствуйте, T4r4sB, Вы писали:
TB>>Вектор, строка, юник не являются тривиально_копиабельными. Но для них тоже можно делать memcpy и memmove. Ну и где?!
V>Что где?! Напиши нормально что ты имеешь в виду.
Я и пишу: если у тебя есть вектор, типом элемента которого является вектор строка или юник, то такой вектор имеет право тупо побитово копировать содержимое, а не гонять зря мув-конструкторы.
V>Если ты имеешь в виду вектор векторов, то какой там memcpy
Обычный такой memcpy, в чём проблема?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте