Exception-safe vector
От: Максим Россия  
Дата: 19.12.22 11:01
Оценка:
Тут смотрю Mock-интервью по плюсам, в одном из них попросили написать человека класс vector. Заинтересовал подход для реализации метода resize, у них он называется "подход с vector_base", с 57:10 про него говорят. Это про то, как обрабатывать ситуацию, когда во время resize удалось выделить новый буфер под данные, но при копировании в него какой-то конструктор копирования бросил исключение и теперь, для всех скопированных элементов надо вызвать деструктор. Никто не сталкивался с таким? И еще вопрос, как вам факт использования try/catch в классе вектора, не режет глаз? Нельзя ли без него как-то обойтись (видимо надо будет использовать RAII обертку)?

https://youtu.be/n5ddGADQIqY?t=3431
Errare humanum est
Re: Exception-safe vector
От: Sm0ke Россия ksi
Дата: 19.12.22 16:35
Оценка: +1
Здравствуйте, Максим, Вы писали:

М>Тут смотрю 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.
Отредактировано 19.12.2022 16:40 Sm0ke . Предыдущая версия . Еще …
Отредактировано 19.12.2022 16:38 Sm0ke . Предыдущая версия .
Re: Exception-safe vector
От: sergii.p  
Дата: 19.12.22 16:59
Оценка:
Здравствуйте, Максим, Вы писали:

М>Тут смотрю Mock-интервью по плюсам, в одном из них попросили написать человека класс vector. Заинтересовал подход для реализации метода resize


меня больше удивило, что этот подход используется в стандартных реализациях.
Разве что-то типа такого будет оверхедом?

void my_vector::resize(const size_t new_size)
{
    if(needRealloc()) {
        my_vector tmp;
        tmp.reserve(new_size);
        for(const auto& el: *this) {
            tmp.push_back(el);
        }
        std::swap(tmp, *this);
    }
}
Re: Exception-safe vector
От: T4r4sB Россия  
Дата: 19.12.22 18:15
Оценка: +2 -1 :))
Здравствуйте, Максим, Вы писали:

М>Тут смотрю Mock-интервью по плюсам, в одном из них попросили написать человека класс vector. Заинтересовал подход для реализации метода resize, у них он называется "подход с vector_base", с 57:10 про него говорят. Это про то, как обрабатывать ситуацию, когда во время resize удалось выделить новый буфер под данные, но при копировании в него какой-то конструктор копирования бросил исключение и теперь, для всех скопированных элементов надо вызвать деструктор. Никто не сталкивался с таким? И еще вопрос, как вам факт использования try/catch в классе вектора, не режет глаз? Нельзя ли без него как-то обойтись (видимо надо будет использовать RAII обертку)?


Самое дикое, что для всех когда-либо реально используемых мной классов достаточно тупо побитового копирования с удалением старого блока без вызова деструкторов. С++ переусложняет ситуацию на ровном месте
Re[2]: Exception-safe vector
От: T4r4sB Россия  
Дата: 19.12.22 18:17
Оценка:
Здравствуйте, Sm0ke, Вы писали:

S> Или move конструктор элементов должен быть noexcept.


Как он может быть НЕ noexcept? Не, я в курсе, что конструкции языка такое допускают. Но как такое на практике вообще блин возможно? И как оно должно отрабатывать при исключении?
Re[2]: Exception-safe vector
От: Sm0ke Россия ksi
Дата: 19.12.22 19:48
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Здравствуйте, Максим, Вы писали:


М>>Тут смотрю Mock-интервью по плюсам, в одном из них попросили написать человека класс vector. Заинтересовал подход для реализации метода resize, у них он называется "подход с vector_base", с 57:10 про него говорят. Это про то, как обрабатывать ситуацию, когда во время resize удалось выделить новый буфер под данные, но при копировании в него какой-то конструктор копирования бросил исключение и теперь, для всех скопированных элементов надо вызвать деструктор. Никто не сталкивался с таким? И еще вопрос, как вам факт использования try/catch в классе вектора, не режет глаз? Нельзя ли без него как-то обойтись (видимо надо будет использовать RAII обертку)?


TB>Самое дикое, что для всех когда-либо реально используемых мной классов достаточно тупо побитового копирования с удалением старого блока без вызова деструкторов. С++ переусложняет ситуацию на ровном месте


Вот по этому люди и велосипедят собственные векторы со своим способом копирования переноса элементов))
Re[2]: Exception-safe vector
От: vsb Казахстан  
Дата: 19.12.22 20:18
Оценка:
Здравствуйте, T4r4sB, Вы писали:

М>>Тут смотрю Mock-интервью по плюсам, в одном из них попросили написать человека класс vector. Заинтересовал подход для реализации метода resize, у них он называется "подход с vector_base", с 57:10 про него говорят. Это про то, как обрабатывать ситуацию, когда во время resize удалось выделить новый буфер под данные, но при копировании в него какой-то конструктор копирования бросил исключение и теперь, для всех скопированных элементов надо вызвать деструктор. Никто не сталкивался с таким? И еще вопрос, как вам факт использования try/catch в классе вектора, не режет глаз? Нельзя ли без него как-то обойтись (видимо надо будет использовать RAII обертку)?


TB>Самое дикое, что для всех когда-либо реально используемых мной классов достаточно тупо побитового копирования с удалением старого блока без вызова деструкторов. С++ переусложняет ситуацию на ровном месте


Как понять побитового копирования? А если класс вида class C { char data[16]; char *data_ptr; };, где data_ptr это указатель на один из элементов data?
Отредактировано 19.12.2022 20:19 vsb . Предыдущая версия . Еще …
Отредактировано 19.12.2022 20:18 vsb . Предыдущая версия .
Re[3]: Exception-safe vector
От: T4r4sB Россия  
Дата: 19.12.22 20:22
Оценка:
Здравствуйте, vsb, Вы писали:

vsb> А если класс вида class C { char data[16]; char *data_ptr; };, где data_ptr это указатель на один из элементов data?


Ты реально таким штукам прописываешь мув-конструктор? Или просто стараешься не гонять по памяти? Типа хранить в юнике на крайнях и всё такое.
Re[3]: Exception-safe vector
От: Stanislav V. Zudin Россия  
Дата: 19.12.22 20:27
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Как понять побитового копирования? А если класс вида class C { char data[16]; char *data_ptr; };, где data_ptr это указатель на один из элементов data?


Ну если не использовать указатели, перейти на индексы, в массивах хранить POD'ы, то получается запросто.
При правильном применении этот подход даёт ощутимые ништяки.

Но такие структуры применимы не везде.
_____________________
С уважением,
Stanislav V. Zudin
Re[2]: Exception-safe vector
От: Videoman Россия https://hts.tv/
Дата: 19.12.22 22:02
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Самое дикое, что для всех когда-либо реально используемых мной классов достаточно тупо побитового копирования с удалением старого блока без вызова деструкторов. С++ переусложняет ситуацию на ровном месте


Что он переусложняет-то? Он наоборот упрощает. Тебе не нужно думать об этом. Если класс trivially copyable, то: string, vector или любой другой последовательный контейнер, сам будет использовать memcpy и memmove.
Re[2]: Exception-safe vector
От: Максим Россия  
Дата: 20.12.22 07:48
Оценка:
S>А если move конструкторы, то как? Не мувать же их обратно... Или move конструктор элементов должен быть noexcept.
У меня аналогичный вопрос возник...
Можно в теории проверять во время компиляции есть ли у оператора перемещения директива noexcept и если есть, то делать move, а иначе копировать. Но выглядит как-то сложновато.
Errare humanum est
Отредактировано 20.12.2022 7:52 Максим . Предыдущая версия .
Re[2]: Exception-safe vector
От: flаt  
Дата: 20.12.22 07:49
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Самое дикое, что для всех когда-либо реально используемых мной классов достаточно тупо побитового копирования с удалением старого блока без вызова деструкторов. С++ переусложняет ситуацию на ровном месте


Вроде как есть (должны быть) специализации операций над вектором с упрощённой логикой для таких типов.
Re[3]: Exception-safe vector
От: T4r4sB Россия  
Дата: 20.12.22 07:50
Оценка:
Здравствуйте, Videoman, Вы писали:

V> сам будет использовать memcpy и memmove.


Вектор, строка, юник не являются тривиально_копиабельными. Но для них тоже можно делать memcpy и memmove. Ну и где?!
Re[3]: Exception-safe vector
От: T4r4sB Россия  
Дата: 20.12.22 08:01
Оценка:
Здравствуйте, flаt, Вы писали:

F>Вроде как есть (должны быть) специализации операций над вектором с упрощённой логикой для таких типов.


Для каких таких? Для строк, юников, деревьев, хеш-таблиц, других векторов — всех их можно побитово копировать. Но вместо этого делается поэлементный мув. Когда изобретут такую оптимизацию?
Re[2]: Exception-safe vector
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 20.12.22 08:05
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>
 tmp.push_back(el);

Тогда уж tmp.emplace_back(el)
Sic luceat lux!
Re[3]: Exception-safe vector
От: T4r4sB Россия  
Дата: 20.12.22 08:19
Оценка:
Здравствуйте, Kernan, Вы писали:

K>Здравствуйте, sergii.p, Вы писали:


SP>>
 tmp.push_back(el);

K>Тогда уж tmp.emplace_back(el)

В данном случае — никакой разницы. По ссылке принимаем аргумент для конструктора копирования, элемент конструируем по месту...
Re[3]: Exception-safe vector
От: sergii.p  
Дата: 20.12.22 08:22
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Здравствуйте, Sm0ke, Вы писали:


S>> Или move конструктор элементов должен быть noexcept.


TB>Как он может быть НЕ noexcept? Не, я в курсе, что конструкции языка такое допускают. Но как такое на практике вообще блин возможно? И как оно должно отрабатывать при исключении?


что здесь удивительного? Разработчик забыл поставить noexcept и получил копирование в векторе. Всё в стиле C++: не доглядел — отстрелил ногу.
Re[4]: Exception-safe vector
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 20.12.22 08:50
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>что здесь удивительного? Разработчик забыл поставить noexcept и получил копирование в векторе. Всё в стиле C++: не доглядел — отстрелил ногу.

Ну почему отстрелил? Просто не произвёл тонкую настройку .
Sic luceat lux!
Re[4]: Exception-safe vector
От: Videoman Россия https://hts.tv/
Дата: 20.12.22 10:20
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Вектор, строка, юник не являются тривиально_копиабельными. Но для них тоже можно делать memcpy и memmove. Ну и где?!


Что где?! Напиши нормально что ты имеешь в виду. Внутри себя вектор, строка и т.д. и так будут использовать memcpy и memmove, если тип их значения тривиально копируемый. Если ты имеешь в виду вектор векторов, то какой там memcpy
Отредактировано 20.12.2022 10:21 Videoman . Предыдущая версия .
Re[5]: Exception-safe vector
От: T4r4sB Россия  
Дата: 20.12.22 12:14
Оценка: -1
Здравствуйте, Videoman, Вы писали:

V>Здравствуйте, T4r4sB, Вы писали:


TB>>Вектор, строка, юник не являются тривиально_копиабельными. Но для них тоже можно делать memcpy и memmove. Ну и где?!


V>Что где?! Напиши нормально что ты имеешь в виду.


Я и пишу: если у тебя есть вектор, типом элемента которого является вектор строка или юник, то такой вектор имеет право тупо побитово копировать содержимое, а не гонять зря мув-конструкторы.

V>Если ты имеешь в виду вектор векторов, то какой там memcpy


Обычный такой memcpy, в чём проблема?
Отредактировано 20.12.2022 12:15 T4r4sB . Предыдущая версия .
Re[6]: Exception-safe vector
От: Videoman Россия https://hts.tv/
Дата: 20.12.22 14:49
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Я и пишу: если у тебя есть вектор, типом элемента которого является вектор строка или юник, то такой вектор имеет право тупо побитово копировать содержимое, а не гонять зря мув-конструкторы.


А кто будет занулять поля в векторе источнике ? Насколько сильно move конструктор вектора бьет по производительности, это ж 4-ре поля, грубо?
Re[7]: Exception-safe vector
От: T4r4sB Россия  
Дата: 20.12.22 14:55
Оценка:
Здравствуйте, Videoman, Вы писали:

V>А кто будет занулять поля в векторе источнике ?


Зачем?
Вот, ещё раз прочитай:
> с удалением старого блока без вызова деструкторов
нахрена занулять поля, если место, занимаемое старым вектором, сразу освобождаем, без вызова деструктора?

V>Насколько сильно move конструктор вектора бьет по производительности, это ж 4-ре поля, грубо?


Не знаю, он же ещё оригинал зануляет, а потом ещё у оригинала деструктор вызывается.
Re[8]: Exception-safe vector
От: Videoman Россия https://hts.tv/
Дата: 20.12.22 15:02
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>нахрена занулять поля, если место, занимаемое старым вектором, сразу освобождаем, без вызова деструктора?


Ты С++ часом со Rust не путаешь. Объект после move может быть переприсвоен и должен быть готов к assign(). Мне кажется ты слишком частный случай рассматриваешь.
Re[9]: Exception-safe vector
От: T4r4sB Россия  
Дата: 20.12.22 15:16
Оценка: +1
Здравствуйте, Videoman, Вы писали:

V>Ты С++ часом со Rust не путаешь. Объект после move может быть переприсвоен и должен быть готов к assign(). Мне кажется ты слишком частный случай рассматриваешь.


Ты до сих пор не заметил, что разговор идёт о move внутри vector::resize? Как ты сможешь обратиться к "старому объекту"?!
Re[10]: Exception-safe vector
От: Stanislav V. Zudin Россия  
Дата: 20.12.22 15:25
Оценка:
Здравствуйте, T4r4sB, Вы писали:

V>>Ты С++ часом со Rust не путаешь. Объект после move может быть переприсвоен и должен быть готов к assign(). Мне кажется ты слишком частный случай рассматриваешь.


TB>Ты до сих пор не заметил, что разговор идёт о move внутри vector::resize? Как ты сможешь обратиться к "старому объекту"?!


А перемещаемый объект внутри vector::resize может иметь указатели? Без к-тора/оператора перемещения ты никак их не поправишь. И получишь мусор в векторе после resize.
_____________________
С уважением,
Stanislav V. Zudin
Re[9]: Exception-safe vector
От: sergii.p  
Дата: 20.12.22 15:32
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Здравствуйте, T4r4sB, Вы писали:


TB>>нахрена занулять поля, если место, занимаемое старым вектором, сразу освобождаем, без вызова деструктора?


V>Ты С++ часом со Rust не путаешь. Объект после move может быть переприсвоен и должен быть готов к assign(). Мне кажется ты слишком частный случай рассматриваешь.


так вопрос видимо об этом. Почему не сделать как в Rust? Сейчас мы платим за то, что не используем (вызываем деструкторы у пустых объектов).
Прописать в стандарте, что после перемещения обращение к объекту является ошибкой — и все проблемы решены. Ещё use after move показывает свои уши в случае когда хочется влепить const, но не можешь, потому как потом хочешь переместить. Но это уже стилистические вопросы. В общем, одна ошибка(?) и куча негативных последствий для языка.
А про 4 рубля — это как посмотреть. Возвращаясь к теме, такой простой код за счёт переаллокаций вектора вызовет N ненужных деструкторов.
std::vector<std::string> res;
for(auto&& word: largeCollection) {
    res.push_back(std::move(word));
}

Оно конечно 4 рубля, но помножить на N.
Отредактировано 20.12.2022 15:38 sergii.p . Предыдущая версия .
Re[11]: Exception-safe vector
От: T4r4sB Россия  
Дата: 20.12.22 15:41
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>А перемещаемый объект внутри vector::resize может иметь указатели?


Ну да, строка, вектор, юник, например.

SVZ>Без к-тора/оператора перемещения ты никак их не поправишь. И получишь мусор в векторе после resize.


Зачем поправлять указатели? Что ты собрался поправлять в строке, векторе, юнике? Не будет мусора, всё будет в порядке.
Re[12]: Exception-safe vector
От: Stanislav V. Zudin Россия  
Дата: 20.12.22 15:51
Оценка:
Здравствуйте, T4r4sB, Вы писали:

SVZ>>А перемещаемый объект внутри vector::resize может иметь указатели?


TB>Ну да, строка, вектор, юник, например.


SVZ>>Без к-тора/оператора перемещения ты никак их не поправишь. И получишь мусор в векторе после resize.


TB>Зачем поправлять указатели? Что ты собрался поправлять в строке, векторе, юнике? Не будет мусора, всё будет в порядке.


У нас вектор может хранить только ограниченный набор типов?
Я говорю про такую ситуацию (псевдокод):
class Fufel
{
  TopSecretContainer* parent; // <-- Указатель на родительский контейнер
  int something = 42;
};

class TopSecretContainer
{
private:
   Fufel fufel1;
   Fufel fufel2;
};

std::vector<TopSecretContainer> topSecrets;


После резайза вектора topSecrets тело TopSecretContainer'а переехало, а указатели у дочерних фуфелов продолжают указывать на старое место в памяти.
Вместо гипотетического TopSecretContainer вполне может оказаться какой-нить std::map или хеш. Или какая-нибудь развесистая DOM-модель.
_____________________
С уважением,
Stanislav V. Zudin
Re[13]: Exception-safe vector
От: T4r4sB Россия  
Дата: 20.12.22 15:54
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>Я говорю про такую ситуацию (псевдокод)


Ну в таком случае конечно не прокатит. А ты таким классам реально честно прописываешь мув-конструктор, хранишь их в векторе? То есть не пытаешься их сразу запихать в юник, чтоб по памяти не гонять?
Re[14]: Exception-safe vector
От: Stanislav V. Zudin Россия  
Дата: 20.12.22 15:58
Оценка:
Здравствуйте, T4r4sB, Вы писали:

SVZ>>Я говорю про такую ситуацию (псевдокод)


TB>Ну в таком случае конечно не прокатит. А ты таким классам реально честно прописываешь мув-конструктор, хранишь их в векторе? То есть не пытаешься их сразу запихать в юник, чтоб по памяти не гонять?


Да я вообще стараюсь указателями не пользоваться.
Для развесистых структур у меня, вместо указателей, используются индексы в массивах.

Но т.к. std::vector — контейнер общего назначения, то и реализация у него универсальная.
В своих массивах у нас и память выделялась по-другому и конструкторы/деструкторы у элементов не вызывались. Но хранились там только POD'ы.
_____________________
С уважением,
Stanislav V. Zudin
Re[15]: Exception-safe vector
От: T4r4sB Россия  
Дата: 20.12.22 16:02
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>Да я вообще стараюсь указателями не пользоваться.

SVZ>Для развесистых структур у меня, вместо указателей, используются индексы в массивах.

Дык отож

SVZ>Но т.к. std::vector — контейнер общего назначения, то и реализация у него универсальная.


И поэтому тащит оверхед ради ситуации, которой никто из известных мне людей не пользуется.
Блин, уж добавили бы тогда лучше is_trivially_movable, с какими-то правилами, под которые бы попали почти все реально существующие классы, кроме тех, которые мувать вообще нельзя.
А так хрень какая-то. С++ опять не платит за то, чем не пользуется, ага.
Re[10]: Exception-safe vector
От: T4r4sB Россия  
Дата: 20.12.22 16:14
Оценка: 2 (1)
Здравствуйте, sergii.p, Вы писали:

SP>Прописать в стандарте, что после перемещения обращение к объекту является ошибкой — и все проблемы решены.

std::string S[5];
std::string A = S[rand() % 5];
std::string B = S[0]; // как это разруливать?

Ну Раст мочит весь массив, ты так же хочешь?
Re[11]: Exception-safe vector
От: sergii.p  
Дата: 20.12.22 17:08
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Здравствуйте, sergii.p, Вы писали:


SP>>Прописать в стандарте, что после перемещения обращение к объекту является ошибкой — и все проблемы решены.

TB>
TB>std::string S[5];
TB>std::string A = S[rand() % 5];
TB>std::string B = S[0]; // как это разруливать?
TB>

TB>Ну Раст мочит весь массив, ты так же хочешь?

да, аргумент интересный. Не думал об этом.
Re[2]: Exception-safe vector
От: B0FEE664  
Дата: 20.12.22 17:55
Оценка: 2 (1)
Здравствуйте, T4r4sB, Вы писали:

TB>Самое дикое, что для всех когда-либо реально используемых мной классов достаточно тупо побитового копирования с удалением старого блока без вызова деструкторов. С++ переусложняет ситуацию на ровном месте


Это, "конечно", аргумент.
Вот простой пример, когда тупое побитовое копирование не пройдёт:

struct B
{
  char  m_data[8]; 
  char* m_pos = m_data;
};
И каждый день — без права на ошибку...
Re[3]: Exception-safe vector
От: T4r4sB Россия  
Дата: 20.12.22 17:59
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Вот простой пример, когда тупое побитовое копирование не пройдёт:


Ты реально таким штукам прописываешь мув-конструктор и потом хранишь их в векторе без посредников? Или просто стараешься не гонять по памяти? Типа хранить в юнике на крайнях и всё такое.
Просто я тоже могу таких примеров придумать. Но не могу вспомнить, когда подобное реально было нужно, да ещё и в векторе.
Re[3]: Exception-safe vector
От: Sm0ke Россия ksi
Дата: 20.12.22 23:17
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Здравствуйте, T4r4sB, Вы писали:


М>>>Тут смотрю Mock-интервью по плюсам, в одном из них попросили написать человека класс vector. Заинтересовал подход для реализации метода resize, у них он называется "подход с vector_base", с 57:10 про него говорят. Это про то, как обрабатывать ситуацию, когда во время resize удалось выделить новый буфер под данные, но при копировании в него какой-то конструктор копирования бросил исключение и теперь, для всех скопированных элементов надо вызвать деструктор. Никто не сталкивался с таким? И еще вопрос, как вам факт использования try/catch в классе вектора, не режет глаз? Нельзя ли без него как-то обойтись (видимо надо будет использовать RAII обертку)?


TB>>Самое дикое, что для всех когда-либо реально используемых мной классов достаточно тупо побитового копирования с удалением старого блока без вызова деструкторов. С++ переусложняет ситуацию на ровном месте


vsb>Как понять побитового копирования? А если класс вида class C { char data[16]; char *data_ptr; };, где data_ptr это указатель на один из элементов data?


Очевидно тут надо хранить индекс, если хочешь memcpy-ем двигать
Re[4]: Exception-safe vector
От: B0FEE664  
Дата: 21.12.22 10:57
Оценка:
Здравствуйте, T4r4sB, Вы писали:

BFE>>Вот простой пример, когда тупое побитовое копирование не пройдёт:

TB>Ты реально таким штукам прописываешь мув-конструктор и потом хранишь их в векторе без посредников?
вот тут пример
Автор: B0FEE664
Дата: 24.03.21
кода похожего на настоящий. Я не помню зачем тогда он мне понадобился и — да, пришлось прописать конструкторы.
Я не помню, есть ли у меня вектор таких объектов.

TB> Или просто стараешься не гонять по памяти? Типа хранить в юнике на крайнях и всё такое.

TB>Просто я тоже могу таких примеров придумать. Но не могу вспомнить, когда подобное реально было нужно, да ещё и в векторе.
Я вообще крайне редко храню в векторе структуры и классы с данными. В основном в векторах лежат smart_ptr'ы и unique_ptr'ы, а их тоже нельзя, согласно стандарту и согласно логике, побитово копировать.
Что же касается объединений, то могу сказать, что их использование требует крайне вдумчивого кода, что занимает прорву времени и множество проверок/assert'ов. А после того как стал доступен std::variant, я вообще не вижу смыла использовать union.
И каждый день — без права на ошибку...
Re[5]: Exception-safe vector
От: Sm0ke Россия ksi
Дата: 21.12.22 11:33
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Здравствуйте, T4r4sB, Вы писали:


BFE>>>Вот простой пример, когда тупое побитовое копирование не пройдёт:

TB>>Ты реально таким штукам прописываешь мув-конструктор и потом хранишь их в векторе без посредников?
BFE>вот тут пример
Автор: B0FEE664
Дата: 24.03.21
кода похожего на настоящий. Я не помню зачем тогда он мне понадобился и — да, пришлось прописать конструкторы.

BFE>Я не помню, есть ли у меня вектор таких объектов.

Есть же std::span

TB>> Или просто стараешься не гонять по памяти? Типа хранить в юнике на крайнях и всё такое.

TB>>Просто я тоже могу таких примеров придумать. Но не могу вспомнить, когда подобное реально было нужно, да ещё и в векторе.
BFE>Я вообще крайне редко храню в векторе структуры и классы с данными. В основном в векторах лежат smart_ptr'ы и unique_ptr'ы, а их тоже нельзя, согласно стандарту и согласно логике, побитово копировать.
BFE>Что же касается объединений, то могу сказать, что их использование требует крайне вдумчивого кода, что занимает прорву времени и множество проверок/assert'ов. А после того как стал доступен std::variant, я вообще не вижу смыла использовать union.

В варианте мне не хватает способа обратиться к значению без проверок.
get<some_type>(var) делает проверку и кидает исключение в случае чего.
Нужен ещё get_unsafe<>() хз как его лучше назвать. На случай когда я точно знаю что за тип хранится в варике.
Re[5]: Exception-safe vector
От: T4r4sB Россия  
Дата: 21.12.22 11:39
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE> В основном в векторах лежат smart_ptr'ы и unique_ptr'ы, а их тоже нельзя, согласно стандарту и согласно логике, побитово копировать.


Их тоже можно, никаких проблем.

BFE>вот тут пример кода похожего на настоящий. Я не помню зачем тогда он мне понадобился и — да, пришлось прописать конструкторы.


Мув-конструктор?
Re[6]: Exception-safe vector
От: PM  
Дата: 21.12.22 22:52
Оценка:
Здравствуйте, Sm0ke, Вы писали:

S>В варианте мне не хватает способа обратиться к значению без проверок.

S>get<some_type>(var) делает проверку и кидает исключение в случае чего.
S>Нужен ещё get_unsafe<>() хз как его лучше назвать. На случай когда я точно знаю что за тип хранится в варике.

Вообще-то есть https://en.cppreference.com/w/cpp/utility/variant/get_if
Re[7]: Exception-safe vector
От: Sm0ke Россия ksi
Дата: 22.12.22 01:34
Оценка:
Здравствуйте, PM, Вы писали:

PM>Здравствуйте, Sm0ke, Вы писали:


S>>В варианте мне не хватает способа обратиться к значению без проверок.

S>>get<some_type>(var) делает проверку и кидает исключение в случае чего.
S>>Нужен ещё get_unsafe<>() хз как его лучше назвать. На случай когда я точно знаю что за тип хранится в варике.

PM>Вообще-то есть https://en.cppreference.com/w/cpp/utility/variant/get_if


If pv is not a null pointer and pv->index() == I

Следовательно оно внутри проверяет состояние. Это оверхед, когда index уже известен.
upd: Да он ещё и указатель проверяет ...
Отредактировано 22.12.2022 1:35 Sm0ke . Предыдущая версия .
Re[6]: Exception-safe vector
От: B0FEE664  
Дата: 22.12.22 11:10
Оценка:
Здравствуйте, Sm0ke, Вы писали:

S>Есть же std::span

Не всем ещё доступен C++20.

S>В варианте мне не хватает способа обратиться к значению без проверок.

Согласен, но для меня это проблемы не составляет.

S>get<some_type>(var) делает проверку и кидает исключение в случае чего.

S>Нужен ещё get_unsafe<>() хз как его лучше назвать. На случай когда я точно знаю что за тип хранится в варике.
Добавить get<T>() как член класса.
И каждый день — без права на ошибку...
Re[6]: Exception-safe vector
От: B0FEE664  
Дата: 22.12.22 11:25
Оценка:
Здравствуйте, T4r4sB, Вы писали:

BFE>> В основном в векторах лежат smart_ptr'ы и unique_ptr'ы, а их тоже нельзя, согласно стандарту и согласно логике, побитово копировать.

TB>Их тоже можно, никаких проблем.
Раз есть приватная часть класса, то, если мне не изменяет память, согласно стандарту — нельзя.

BFE>>вот тут пример кода похожего на настоящий. Я не помню зачем тогда он мне понадобился и — да, пришлось прописать конструкторы.

TB>Мув-конструктор?

Да. А что?
И каждый день — без права на ошибку...
Re[7]: Exception-safe vector
От: T4r4sB Россия  
Дата: 22.12.22 12:17
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Раз есть приватная часть класса, то, если мне не изменяет память, согласно стандарту — нельзя.


Я не про "по стандарту", а "по факту". Любой реально полезный класс по факту можно. Кроме тех, где есть указатель на буфер, хранящийся внутри него же, и такие классы обычно вообще запрещают перемещать.

BFE>Да. А что?


Ну, крайне редкий случай, я считаю, который очень легко обходится.
Re[8]: Exception-safe vector
От: B0FEE664  
Дата: 22.12.22 13:47
Оценка:
Здравствуйте, T4r4sB, Вы писали:

BFE>>Раз есть приватная часть класса, то, если мне не изменяет память, согласно стандарту — нельзя.

TB>Я не про "по стандарту", а "по факту". Любой реально полезный класс по факту можно. Кроме тех, где есть указатель на буфер, хранящийся внутри него же, и такие классы обычно вообще запрещают перемещать.

"По факту" массивы (контейнеры) вообще не нужны, достаточно массивов указателей. Но тогда это не C++.

BFE>>Да. А что?

TB>Ну, крайне редкий случай, я считаю, который очень легко обходится.

Нет, крайне редкий случай, это когда объект хранит в себе все указатели на себя и меняет их при своём перемещении.
И каждый день — без права на ошибку...
Re[9]: Exception-safe vector
От: T4r4sB Россия  
Дата: 22.12.22 13:49
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>"По факту" массивы (контейнеры) вообще не нужны, достаточно массивов указателей. Но тогда это не C++.


Это вообще к чему?

BFE>Нет, крайне редкий случай, это когда объект хранит в себе все указатели на себя и меняет их при своём перемещении.


Да. Поэтому вектор может тупо побитово копировать содержимое в resize, не нужна эта вся пляска с мув-конструкторами.
Re[10]: Exception-safe vector
От: B0FEE664  
Дата: 22.12.22 13:57
Оценка:
Здравствуйте, T4r4sB, Вы писали:

BFE>>"По факту" массивы (контейнеры) вообще не нужны, достаточно массивов указателей. Но тогда это не C++.

TB>Это вообще к чему?
К тому, что в С++ один объект может указывать внутрь другого объекта. Если бы было иначе, то можно было бы очень сильно поменять работу с указателями, но это был бы уже не C++.

BFE>>Нет, крайне редкий случай, это когда объект хранит в себе все указатели на себя и меняет их при своём перемещении.

TB>Да. Поэтому вектор может тупо побитово копировать содержимое в resize, не нужна эта вся пляска с мув-конструкторами.
Нет, редкие ситуации тоже должны нормально отрабатывать.
А если вам не надо как в векторе, то напишите свой контейнер — никто не запрещает же.
И каждый день — без права на ошибку...
Re[11]: Exception-safe vector
От: T4r4sB Россия  
Дата: 22.12.22 15:40
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>К тому, что в С++ один объект может указывать внутрь другого объекта.


Это не проблема. Юники, строки, вектора — указывают, и что? Их спокойно можно побитово копировать внутре vector::resize
А если ты имеешь ссылки на элемент вектора в каком-то левом объекте — то ну ты сам понимаешь же что так нельзя?

BFE>Если бы было иначе, то можно было бы очень сильно поменять работу с указателями, но это был бы уже не C++.


Да, это был бы более быстрый и оптимальный язык, который бы мог юник в регистре передавать. Но С++ же снова "не платит за то чего не использует".

BFE>Нет, редкие ситуации тоже должны нормально отрабатывать.

BFE>А если вам не надо как в векторе, то напишите свой контейнер — никто не запрещает же.

Это редкие ситуации мне и большинству коллег не встречались никогда.
Re[12]: Exception-safe vector
От: B0FEE664  
Дата: 22.12.22 16:47
Оценка:
Здравствуйте, T4r4sB, Вы писали:

BFE>>К тому, что в С++ один объект может указывать внутрь другого объекта.

TB>Это не проблема. Юники, строки, вектора — указывают, и что? Их спокойно можно побитово копировать внутре vector::resize
TB>А если ты имеешь ссылки на элемент вектора в каком-то левом объекте — то ну ты сам понимаешь же что так нельзя?

Почему в "левом" объекте? Вот итератор по вектору — объект совсем не левый, но он после resize станет невалидным. Можно ли написать итератор, что останется валидным после resize? Это запросто, но такой итератор будет медленнее.

BFE>>Если бы было иначе, то можно было бы очень сильно поменять работу с указателями, но это был бы уже не C++.

TB>Да, это был бы более быстрый и оптимальный язык, который бы мог юник в регистре передавать. Но С++ же снова "не платит за то чего не использует".
Если бы нельзя было указывать внутрь объекта, то язык был бы медленнее, так как нельзя было бы написать быстрые итераторы.

BFE>>Нет, редкие ситуации тоже должны нормально отрабатывать.

BFE>>А если вам не надо как в векторе, то напишите свой контейнер — никто не запрещает же.
TB>Это редкие ситуации мне и большинству коллег не встречались никогда.
Да ладно! Никогда не хранили дерево в векторе?
И каждый день — без права на ошибку...
Re[13]: Exception-safe vector
От: T4r4sB Россия  
Дата: 22.12.22 16:56
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Почему в "левом" объекте? Вот итератор по вектору — объект совсем не левый, но он после resize станет невалидным. Можно ли написать итератор, что останется валидным после resize? Это запросто, но такой итератор будет медленнее.


Ну значит не надо использовать такой итератор, а это к чему?

BFE>Если бы нельзя было указывать внутрь объекта, то язык был бы медленнее, так как нельзя было бы написать быстрые итераторы.


Чего? Я вообще не понял, ты про что? Как "ссылки внутрь объекта" мешают побитово копировать объект в vector::resize, при условии, что правила использования итераторов и ссылок такие же, как сейчас?

BFE>Да ладно! Никогда не хранили дерево в векторе?


Не хранил, но даже если б и хранил, то какая разница? Ты будешь называть новые названия стандартных классов? Их все можно побитово копировать, старайся дальше. Ну кроме изначально немувабельных.
Re[14]: Exception-safe vector
От: B0FEE664  
Дата: 22.12.22 18:15
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB> Как "ссылки внутрь объекта" мешают побитово копировать объект в vector::resize, при условии, что правила использования итераторов и ссылок такие же, как сейчас?

Мешают потерей общности: либо вектор не универсальный, либо итераторы медленные.

BFE>>Да ладно! Никогда не хранили дерево в векторе?

TB>Не хранил, но даже если б и хранил, то какая разница?
Не у всех сложных задач есть простые решения. Если вы не сталкивались с некоторыми типами задач, то это не значит. что другие с ними не сталкивались.

TB>Ты будешь называть новые названия стандартных классов? Их все можно побитово копировать, старайся дальше. Ну кроме изначально немувабельных.

Я встречал программистов, которые не используют шаблоны, и таких программистов, которые не могут понять косвенной адресации, есть такие программисты, что не понимают концепцию виртуального метода, а есть такие, что не используют итераторов. И всё это программисты, которые годами работают на С++ и успешно решают поставленные перед ними задачи. Существуют такие, что даже не могут освоить C++, Torvalds Linux тому пример.
Во многом поэтому все стандартные объекты проектируются структурно простыми. Изначально вектор (как и строка) не обязаны были лежать в памяти одним куском, поэтому можно было написать вектор с быстрым добавлением и удалением элементов, так как не надо было перемещать все эти элементы при вставке нового, но под давлением всей этой массы вектор хранящий непрерывный кусок памяти был стандартизирован столь нелепым способом. (А ведь можно было добавить, скажем, метод align(), но...) И вы мне предлагаете вот из этого набора элементарных структур назвать такие, что нельзя скопировать побитно? Серьёзно? Повторюсь: если вам не надо как в векторе, то напишите свой контейнер — никто не запрещает же. Только вот не надо упрощать то, что и так уже простое.
И каждый день — без права на ошибку...
Re[15]: Exception-safe vector
От: T4r4sB Россия  
Дата: 22.12.22 18:37
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Мешают потерей общности: либо вектор не универсальный, либо итераторы медленные.


Вектор не универсален, да.
А причём тут побитовое копирование объектов?

BFE>>>Да ладно! Никогда не хранили дерево в векторе?

TB>>Не хранил, но даже если б и хранил, то какая разница?
BFE>Не у всех сложных задач есть простые решения. Если вы не сталкивались с некоторыми типами задач, то это не значит. что другие с ними не сталкивались.

Не уходи от ответа, про какие проблемы побитового копирования дерева ты мне пытаешься рассказать?

BFE>Бла-бла-бла


К чему это всё? О_о

BFE> И вы мне предлагаете вот из этого набора элементарных структур назвать такие, что нельзя скопировать побитно?


Да, я это и пытаюсь от тебя добиться. Какие же? Кроме изначально принципиально неперемещаемых.
Назови такие. Без лирических отступлений, мне это нафиг не надо.
Нет таких в стандартных.
Вектор просто переусложнён на пустом месте.
А глупые крестовики продолжают верить, что они не платят за то, чего не используют)
Re[3]: Exception-safe vector
От: wander  
Дата: 22.12.22 22:03
Оценка:
Здравствуйте, Максим, Вы писали:

М>Можно в теории проверять во время компиляции есть ли у оператора перемещения директива noexcept и если есть, то делать move, а иначе копировать. Но выглядит как-то сложновато.


Оно так и происходит.
Re[2]: Exception-safe vector
От: rg45 СССР  
Дата: 22.12.22 22:21
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Самое дикое, что для всех когда-либо реально используемых мной классов достаточно тупо побитового копирования с удалением старого блока без вызова деструкторов. С++ переусложняет ситуацию на ровном месте


Ты предлагаешь этот подход использовать только при реаллокации вектора, или в принципе, везде, где по идее должна выполняться операция перемещения?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: Exception-safe vector
От: rg45 СССР  
Дата: 22.12.22 22:56
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Ты реально таким штукам прописываешь мув-конструктор и потом хранишь их в векторе без посредников? Или просто стараешься не гонять по памяти? Типа хранить в юнике на крайнях и всё такое.


Какая разница, что он реально прописывает. Ссылки и указатели в объектах, направленные внутрь самих себя, не запрещены и время от времени попадаются в коде, плохо это или хорошо. Ты предлагаешь запретить эту возможность, или что?
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 22.12.2022 22:58 rg45 . Предыдущая версия .
Re[3]: Exception-safe vector
От: T4r4sB Россия  
Дата: 23.12.22 09:03
Оценка:
Здравствуйте, rg45, Вы писали:

R>Ты предлагаешь этот подход использовать только при реаллокации вектора, или в принципе, везде, где по идее должна выполняться операция перемещения?


Везде, где можно гарантировать, что старый объект не будет доступен.
Re[5]: Exception-safe vector
От: T4r4sB Россия  
Дата: 23.12.22 09:04
Оценка:
Здравствуйте, rg45, Вы писали:

R>Какая разница, что он реально прописывает. Ссылки и указатели в объектах, направленные внутрь самих себя, не запрещены и время от времени попадаются в коде, плохо это или хорошо. Ты предлагаешь запретить эту возможность, или что?


Я предлагаю запретить эту возможность в перемещаемых объектах. Мне вот ни разу не понадобилась за всё время. Если у меня и делается самоссылка, то объект сидит в юнике или шареде.
Re[6]: Exception-safe vector
От: rg45 СССР  
Дата: 23.12.22 09:35
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Я предлагаю запретить эту возможность в перемещаемых объектах. Мне вот ни разу не понадобилась за всё время. Если у меня и делается самоссылка, то объект сидит в юнике или шареде.


Как должен/может выглядеть этот запрет? Прямо в стандарте языка это прописать?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: Exception-safe vector
От: rg45 СССР  
Дата: 23.12.22 09:39
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Везде, где можно гарантировать, что старый объект не будет доступен.


А как это можно гарантировать? Как минимум, он всегда будет доступен для разработчика, который выполняет операцию перемещения и для того, кто будет этот код сопровождать.

И второй вопрос: а что с текущей концепцией перемещения — перемещающие конструкторы, операторы присваивания, rvalue ссылки и пр. — что-то из этого остается или все упраздняется?
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 23.12.2022 9:41 rg45 . Предыдущая версия .
Re[7]: Exception-safe vector
От: T4r4sB Россия  
Дата: 23.12.22 09:54
Оценка:
Здравствуйте, rg45, Вы писали:

R>Как должен/может выглядеть этот запрет? Прямо в стандарте языка это прописать?


Сказать, что если объект имеет право быть перемещён при возврате из функции или при реаллокации вектора. И если объект содержит ссылки на себя, то это УБ.
Re[5]: Exception-safe vector
От: T4r4sB Россия  
Дата: 23.12.22 09:56
Оценка:
Здравствуйте, rg45, Вы писали:

R>А как это можно гарантировать? Как минимум, он всегда будет доступен для разработчика, который выполняет операцию перемещения и для того, кто будет этот код сопровождать.


В векторе после ::resize объекты старого блока гарантированно недоступны для пользователя вектора.
При возврате поля объекта старое поле гарантированно недоступно для пользователя.

R>И второй вопрос: а что с текущей концепцией перемещения — перемещающие конструкторы, операторы присваивания, rvalue ссылки и пр. — что-то из этого остается или все упраздняется?


Ну std::move придётся оставить, конечно, чтоб эффективно вытащить элемент из вектора, например.
Re[4]: Exception-safe vector
От: rg45 СССР  
Дата: 23.12.22 09:57
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Везде, где можно гарантировать, что старый объект не будет доступен.


Еще вопросик: как в предлагаемом тобой подходе будет выглядеть такой код:

A a;
foo(std::move(a));


Такое возможно будет, или нужно будет тоже запрещать?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[6]: Exception-safe vector
От: rg45 СССР  
Дата: 23.12.22 10:01
Оценка:
Здравствуйте, T4r4sB, Вы писали:


R>>А как это можно гарантировать? Как минимум, он всегда будет доступен для разработчика, который выполняет операцию перемещения и для того, кто будет этот код сопровождать.


TB>В векторе после ::resize объекты старого блока гарантированно недоступны для пользователя вектора.

TB>При возврате поля объекта старое поле гарантированно недоступно для пользователя.

Ты пишешь очевидные вещи, но только про пользователя. А что на счет разработков, которые будут поддерживать ::resize ?

TB>Ну std::move придётся оставить, конечно, чтоб эффективно вытащить элемент из вектора, например.


Не уверен, что правильно понял сценарий использования — эта операцию для кого доступна — для всех пользователей, или только для разработчиков вектора?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[5]: Exception-safe vector
От: T4r4sB Россия  
Дата: 23.12.22 12:11
Оценка:
Здравствуйте, rg45, Вы писали:

R>Такое возможно будет, или нужно будет тоже запрещать?


Да, почему нет?

R>Ты пишешь очевидные вещи, но только про пользователя. А что на счет разработков, которые будут поддерживать ::resize ?


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

R>Не уверен, что правильно понял сценарий использования — эта операцию для кого доступна — для всех пользователей, или только для разработчиков вектора?


Я про такую ситуацию
std::vector<std::string> V("stroka", 6);
std::string S = std::move(V[4]);

После этого V[4] остаётся доступен пользователю и конечно, его надо сохранить в валидном состоянии.

Впрочем, даже мув-конструктор явно лишний. Побитовое копирование из старого в новый, а в старом вызвать конструктор-по-умолчанию. Я не видел сценариев, где реально требуется что-то более сложное. Но вручную писать мув-конструктор всё равно надо. Бесит.
Если же такого конструктора нет, то не разрешать такое.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.