Здравствуйте, T4r4sB, Вы писали:
TB>Я и пишу: если у тебя есть вектор, типом элемента которого является вектор строка или юник, то такой вектор имеет право тупо побитово копировать содержимое, а не гонять зря мув-конструкторы.
А кто будет занулять поля в векторе источнике ? Насколько сильно move конструктор вектора бьет по производительности, это ж 4-ре поля, грубо?
Здравствуйте, Videoman, Вы писали:
V>А кто будет занулять поля в векторе источнике ?
Зачем?
Вот, ещё раз прочитай: > с удалением старого блока без вызова деструкторов
нахрена занулять поля, если место, занимаемое старым вектором, сразу освобождаем, без вызова деструктора?
V>Насколько сильно move конструктор вектора бьет по производительности, это ж 4-ре поля, грубо?
Не знаю, он же ещё оригинал зануляет, а потом ещё у оригинала деструктор вызывается.
Здравствуйте, T4r4sB, Вы писали:
TB>нахрена занулять поля, если место, занимаемое старым вектором, сразу освобождаем, без вызова деструктора?
Ты С++ часом со Rust не путаешь. Объект после move может быть переприсвоен и должен быть готов к assign(). Мне кажется ты слишком частный случай рассматриваешь.
Здравствуйте, Videoman, Вы писали:
V>Ты С++ часом со Rust не путаешь. Объект после move может быть переприсвоен и должен быть готов к assign(). Мне кажется ты слишком частный случай рассматриваешь.
Ты до сих пор не заметил, что разговор идёт о move внутри vector::resize? Как ты сможешь обратиться к "старому объекту"?!
Здравствуйте, T4r4sB, Вы писали:
V>>Ты С++ часом со Rust не путаешь. Объект после move может быть переприсвоен и должен быть готов к assign(). Мне кажется ты слишком частный случай рассматриваешь.
TB>Ты до сих пор не заметил, что разговор идёт о move внутри vector::resize? Как ты сможешь обратиться к "старому объекту"?!
А перемещаемый объект внутри vector::resize может иметь указатели? Без к-тора/оператора перемещения ты никак их не поправишь. И получишь мусор в векторе после resize.
_____________________
С уважением,
Stanislav V. Zudin
Здравствуйте, Videoman, Вы писали:
V>Здравствуйте, T4r4sB, Вы писали:
TB>>нахрена занулять поля, если место, занимаемое старым вектором, сразу освобождаем, без вызова деструктора?
V>Ты С++ часом со Rust не путаешь. Объект после move может быть переприсвоен и должен быть готов к assign(). Мне кажется ты слишком частный случай рассматриваешь.
так вопрос видимо об этом. Почему не сделать как в Rust? Сейчас мы платим за то, что не используем (вызываем деструкторы у пустых объектов).
Прописать в стандарте, что после перемещения обращение к объекту является ошибкой — и все проблемы решены. Ещё use after move показывает свои уши в случае когда хочется влепить const, но не можешь, потому как потом хочешь переместить. Но это уже стилистические вопросы. В общем, одна ошибка(?) и куча негативных последствий для языка.
А про 4 рубля — это как посмотреть. Возвращаясь к теме, такой простой код за счёт переаллокаций вектора вызовет N ненужных деструкторов.
Здравствуйте, 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
Здравствуйте, Stanislav V. Zudin, Вы писали:
SVZ>Я говорю про такую ситуацию (псевдокод)
Ну в таком случае конечно не прокатит. А ты таким классам реально честно прописываешь мув-конструктор, хранишь их в векторе? То есть не пытаешься их сразу запихать в юник, чтоб по памяти не гонять?
Здравствуйте, T4r4sB, Вы писали:
SVZ>>Я говорю про такую ситуацию (псевдокод)
TB>Ну в таком случае конечно не прокатит. А ты таким классам реально честно прописываешь мув-конструктор, хранишь их в векторе? То есть не пытаешься их сразу запихать в юник, чтоб по памяти не гонять?
Да я вообще стараюсь указателями не пользоваться.
Для развесистых структур у меня, вместо указателей, используются индексы в массивах.
Но т.к. std::vector — контейнер общего назначения, то и реализация у него универсальная.
В своих массивах у нас и память выделялась по-другому и конструкторы/деструкторы у элементов не вызывались. Но хранились там только POD'ы.
_____________________
С уважением,
Stanislav V. Zudin
Здравствуйте, Stanislav V. Zudin, Вы писали:
SVZ>Да я вообще стараюсь указателями не пользоваться. SVZ>Для развесистых структур у меня, вместо указателей, используются индексы в массивах.
Дык отож
SVZ>Но т.к. std::vector — контейнер общего назначения, то и реализация у него универсальная.
И поэтому тащит оверхед ради ситуации, которой никто из известных мне людей не пользуется.
Блин, уж добавили бы тогда лучше is_trivially_movable, с какими-то правилами, под которые бы попали почти все реально существующие классы, кроме тех, которые мувать вообще нельзя.
А так хрень какая-то. С++ опять не платит за то, чем не пользуется, ага.
Здравствуйте, 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>
Здравствуйте, T4r4sB, Вы писали:
TB>Самое дикое, что для всех когда-либо реально используемых мной классов достаточно тупо побитового копирования с удалением старого блока без вызова деструкторов. С++ переусложняет ситуацию на ровном месте
Это, "конечно", аргумент.
Вот простой пример, когда тупое побитовое копирование не пройдёт:
struct B
{
char m_data[8];
char* m_pos = m_data;
};
Здравствуйте, B0FEE664, Вы писали:
BFE>Вот простой пример, когда тупое побитовое копирование не пройдёт:
Ты реально таким штукам прописываешь мув-конструктор и потом хранишь их в векторе без посредников? Или просто стараешься не гонять по памяти? Типа хранить в юнике на крайнях и всё такое.
Просто я тоже могу таких примеров придумать. Но не могу вспомнить, когда подобное реально было нужно, да ещё и в векторе.
Здравствуйте, 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-ем двигать
Здравствуйте, T4r4sB, Вы писали:
BFE>>Вот простой пример, когда тупое побитовое копирование не пройдёт: TB>Ты реально таким штукам прописываешь мув-конструктор и потом хранишь их в векторе без посредников? вот тут пример
кода похожего на настоящий. Я не помню зачем тогда он мне понадобился и — да, пришлось прописать конструкторы.
Я не помню, есть ли у меня вектор таких объектов.
TB> Или просто стараешься не гонять по памяти? Типа хранить в юнике на крайнях и всё такое. TB>Просто я тоже могу таких примеров придумать. Но не могу вспомнить, когда подобное реально было нужно, да ещё и в векторе.
Я вообще крайне редко храню в векторе структуры и классы с данными. В основном в векторах лежат smart_ptr'ы и unique_ptr'ы, а их тоже нельзя, согласно стандарту и согласно логике, побитово копировать.
Что же касается объединений, то могу сказать, что их использование требует крайне вдумчивого кода, что занимает прорву времени и множество проверок/assert'ов. А после того как стал доступен std::variant, я вообще не вижу смыла использовать union.
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, T4r4sB, Вы писали:
BFE>>>Вот простой пример, когда тупое побитовое копирование не пройдёт: TB>>Ты реально таким штукам прописываешь мув-конструктор и потом хранишь их в векторе без посредников? BFE>вот тут пример
кода похожего на настоящий. Я не помню зачем тогда он мне понадобился и — да, пришлось прописать конструкторы. BFE>Я не помню, есть ли у меня вектор таких объектов.
Есть же std::span
TB>> Или просто стараешься не гонять по памяти? Типа хранить в юнике на крайнях и всё такое. TB>>Просто я тоже могу таких примеров придумать. Но не могу вспомнить, когда подобное реально было нужно, да ещё и в векторе. BFE>Я вообще крайне редко храню в векторе структуры и классы с данными. В основном в векторах лежат smart_ptr'ы и unique_ptr'ы, а их тоже нельзя, согласно стандарту и согласно логике, побитово копировать. BFE>Что же касается объединений, то могу сказать, что их использование требует крайне вдумчивого кода, что занимает прорву времени и множество проверок/assert'ов. А после того как стал доступен std::variant, я вообще не вижу смыла использовать union.
В варианте мне не хватает способа обратиться к значению без проверок.
get<some_type>(var) делает проверку и кидает исключение в случае чего.
Нужен ещё get_unsafe<>() хз как его лучше назвать. На случай когда я точно знаю что за тип хранится в варике.
Здравствуйте, B0FEE664, Вы писали:
BFE> В основном в векторах лежат smart_ptr'ы и unique_ptr'ы, а их тоже нельзя, согласно стандарту и согласно логике, побитово копировать.
Их тоже можно, никаких проблем.
BFE>вот тут пример кода похожего на настоящий. Я не помню зачем тогда он мне понадобился и — да, пришлось прописать конструкторы.
Здравствуйте, Sm0ke, Вы писали:
S>В варианте мне не хватает способа обратиться к значению без проверок. S>get<some_type>(var) делает проверку и кидает исключение в случае чего. S>Нужен ещё get_unsafe<>() хз как его лучше назвать. На случай когда я точно знаю что за тип хранится в варике.