А был ли мальчик? (помянем плюсы)
-
- Уже с Приветом
- Posts: 8090
- Joined: 08 Nov 2004 12:24
- Location: GA
Re: А был ли мальчик? (помянем плюсы)
И не говорите. Я вот все больше убеждаюсь, что у людей отсутствует элементарный каммон сенс, пытаются рассуждать о высоких материях, не понимая элементарного. Огромное число диванных теоретиков в любой области. А ты потом, после них, смотришь на код и пытаешься вкурить, почему передвинув маленький массив из а на место огромного в б, последний обнаруживается в а. Теперь вот буду знать, поработали спасатели "дорогих ресурсов"
-
- Уже с Приветом
- Posts: 3003
- Joined: 14 Apr 2004 01:11
- Location: SFBA (было: Минск, Беларусь)
Re: А был ли мальчик? (помянем плюсы)
О, это целый пласт!Prosche wrote: 25 Jan 2018 17:21 Огромное число диванных теоретиков в любой области. А ты потом, после них, смотришь на код и пытаешься вкурить, почему передвинув маленький массив из а на место огромного в б, последний обнаруживается в а.
Сразу приходит в голову такой популярный вопрос на Интернете у разработчиков of Bangalor persuasion. Типа: "Я уничтожил свой массив через `delete[]`, а потом заглянул в якобы "уничтоженную" память через этот же указатель, а мои данные там все лежат нетронутые. Как так? Почему? Я же сказал - "уничтожить", а они все равно там!" (Вариации: возвращение указателя на локальный объект и т.д. и т.п. Отдельный плюс: ссылка на значение слова `delete` в Оксфордском словаре. )
И потом приходится вдалбливать нерадивому студенту, что совать свой нос в освобожденную память не нужно. И что то, что там "осталось" или "не осталось" значения не имеет и его касаться/интересовать вообще не должно. Память освобождена - это все, что ему нужно знать. Его массив был концептуально уничтожен.
Но он, как правило, услышав слово "концептуально", начинает лезть в бутылку: первое время обзывает всех "теоретиками", ибо он, жесткий "практик", уже доказал нам всем, что "на практике" ничего не уничтожилось и то он "на практике" этим давно пользуется и у него "на практике" все работает. И т.д. и т.п. Количество времени, требуемое на пробуждение вменяемости у таких "практиков" варьируется в широких пределах. И успех не гарантирован.
Вот, я смотрю, и у вас что-то наблюдается нестерпимое желание совать в свой нос в недра moved from объекта и разглядывать то, что в нем "обнаруживается"... И понять тот факт, что в рамках move semantics это вас вообще не касается и интересовать совершенно не должно, вам похоже, пока не по силам...
Last edited by AndreyT on 25 Jan 2018 19:01, edited 2 times in total.
Best regards,
Андрей
Андрей
-
- Уже с Приветом
- Posts: 8090
- Joined: 08 Nov 2004 12:24
- Location: GA
Re: А был ли мальчик? (помянем плюсы)
когда у вас массив на пару гигов, который вы заменили другим, как вы считаете, на самом деле никуда не денется, а продолжит отжирать память, то вы очень быстро и "под капот" залезете, и все детали имплементации узнаете, и еще и толстый пучок диарейных лучей в направлении автора пошлете.
-
- Уже с Приветом
- Posts: 9195
- Joined: 04 Mar 2011 03:04
- Location: SFBA
Re: А был ли мальчик? (помянем плюсы)
Ну, на практике, когда пользователь моего компонента не может применить стандартную операцию над контейнером данных, полученных от него, можно, конечно, объяснить, что ему необязательно ожидать наличие такой операции в данном конкретном случае. Но обычно они продолжают возмущаться.AndreyT wrote: 23 Jan 2018 19:32 Во-первых, львиная часть идеи шаблонного программирования как раз и заключается в том, что шаблонный класс может содержать операции, неприменимые для некоторых типов шаблонного аргумента, но это нам никак не должно мешать, пока мы не пытаемся эти операции использовать (инстанциировать).
Duly noted. Так и буду отпинывать недовольных моими контейнерами.Во-вторых, ожидание доступности всех операций контейнера - это некий С++98-стиль мышления. В С++98 первичен был сам контейнер: доминировали жесткие требования контейнера, а элемент вынужден был волей-неволей под них подстраиваться, даже если это больше нигде никому не было нужно. И это, вообще-то, плохо, ибо с точки зрения здравого смысла должно быть как раз таки наоборот - свойства элемента контейнера должны быть первичны. И они должны прозрачно проноситься (форвардиться) сквозь контейнер в окружающий мир, также как это работает с "рукописными" голыми массивами, списками и т.п.
static_assert почаще применять для устранения недопониманий... Как в свой код поставить, понятно. А если хочется внятно сообщить о неправильном случае использования стандартного контейнера для конкретного типа?Причем в С++98 такое жесткое доминирование правил контейнера сделали отнюдь не потому что это считалось "правильным", а просто потому, что в языке не было адекватных средств для того, чтобы сделать по-другому. Это стало возможно только в С++11. Но даже и в С++98 допустимые операции над контейнером зависели от определенных свойств элемента, хотя бы на интерфейсном уровне - например, возможность или возможность конструкции по умолчанию для элемента влияла на большое количество возможностей вызова методов контейнера.
... and even then it's rare that you'll be going there...
-
- Уже с Приветом
- Posts: 3003
- Joined: 14 Apr 2004 01:11
- Location: SFBA (было: Минск, Беларусь)
Re: А был ли мальчик? (помянем плюсы)
Мне надоело рассказывать "сказку про белого бычка" снова и снова.Prosche wrote: 25 Jan 2018 18:05 когда у вас массив на пару гигов, который вы заменили другим, как вы считаете, на самом деле никуда не денется, а продолжит отжирать память, то вы очень быстро и "под капот" залезете, и все детали имплементации узнаете, и еще и толстый пучок диарейных лучей в направлении автора пошлете.
Всем прекрасно понятно, что в "среднестатистических" приложениях в 99 случаях из 100 move делается из expiring объекта. То есть moved from объект будет уничтожен практически сразу после того, как из него сделали move. В такой ситуации разница во времени жизни ресурсов в любой реализации move будет сводиться к жалкому десятку тактов процессора. Мove-присваивание, реализованное через swap, тоже с радостью освободит вашу "пару гигов" при деструкции правой части. Так что не надо пугать людей: никто не будет "продолжать отжирать память".
В тех же ситуациях, когда правая часть продолжает долго жить и после move, этот вопрос уже переходит в совсем другую плоскость. Раз он продолжает долго жить, то значит он кому-то нужен? Может быть это и хорошо, что он продолжает отжирать "пару гигов"? Может в него сейчас эти самые "пару гигов" и захотят записать, а он как раз к этому готов?
На такие вопросы не существует ответа вне конкретных контекстов.
И даже в тех ситуациях, когда эти "пару гигов" действительно никому не нужны, вопрос на самом деле уже впрямую и не относится к move semantics. Это на самом деле та же извечная проблема как, например, в `std::vector`, который исторически накопил capacity в ваши "два гига", но сейчас имеет size в какие-то жалкие три байта. Что делать? Может вызывать shrink_to_fit? А может погодить - вдруг сейчас "два гига" таки сразу понадобятся?
Повторюсь: на такие вопросы не существует ответа вне конкретных контекстов.
Best regards,
Андрей
Андрей
-
- Уже с Приветом
- Posts: 8090
- Joined: 08 Nov 2004 12:24
- Location: GA
Re: А был ли мальчик? (помянем плюсы)
Вы начинаете повторяться.AndreyT wrote: 25 Jan 2018 18:57 В тех же ситуациях, когда правая часть продолжает долго жить и после move, этот вопрос уже переходит в совсем другую плоскость. Раз он продолжает долго жить, то значит он кому-то нужен? Может быть это и хорошо, что он продолжает отжирать "пару гигов"? Может в него сейчас эти самые "пару гигов" и захотят записать, а он как раз к этому готов?
На такие вопросы не существует ответа вне конкретных контекстов.
Повторюсь: на такие вопросы не существует ответа вне конкретных контекстов.
Ответ безусловно существует. И он тривиален. В таком случае надо использовать свап. И мув тут совершенно не при делах.
-
- Уже с Приветом
- Posts: 3003
- Joined: 14 Apr 2004 01:11
- Location: SFBA (было: Минск, Беларусь)
Re: А был ли мальчик? (помянем плюсы)
Move semantics для класса в С++ - это не более чем набор special member sunctions (move constructor и move assignment operator), которые служат в качестве интерфейса между рукописным кодом и ядром языка. А также простое "джентельменское соглашение": левая часть должна получить значение правой части, а правая часть должна получить некоторое неспецифицированное, но валидное состояние. Никаких других "надо" или "не надо" тут нет.Prosche wrote: 25 Jan 2018 19:09 Ответ безусловно существует. И он тривиален. В таком случае надо использовать свап. И мув тут совершенно не при делах.
Классическая copy semantics является примером move semantics. Swap semantics тоже является примером move semantics. Можно придумать еще множество разнообразных примеров move semantics. С чего вы взяли, что ваши верования являются Единственным Истинным Способом реализации move semantics мне в упор не ясно.
Best regards,
Андрей
Андрей
-
- Уже с Приветом
- Posts: 803
- Joined: 24 Jan 2007 07:32
- Location: Сергели->Новосибирск->SFBA->Новосибирск->Москва->NY->SFBA
Re: А был ли мальчик? (помянем плюсы)
Если реально столько много их то можно было бы подумать не о куче а о глобальной памяти.ksi wrote: 25 Jan 2018 05:37 А можно unrelated вопрос? У меня была такая ситуация (я не программист в чистом виде, поэтому сорри, если чего не понимаю): мне нужно создать в памяти копии какого объекта. В большом количестве, сотни тысяч или миллионы потенциально. Поинтеры на новые объекты куда-то положить, ну в массив например. Есть какой-нибудь трюк чтобы это сделать наиболее быстро или ничего кроме цикла из memcpy нельзя придумать? И второй вопрос - а можно это как-то multithreaded или memory manager все равно не способен параллельно выделять память? Или нужен специальный memory manager, которые могут это поддержать? Такие есть?
Если вы знаете верхний предел то можно выделить сразу большой кусок.
Спи быстрее, твоя подушка нужна другому. Copyright Зощенко
-
- Уже с Приветом
- Posts: 803
- Joined: 24 Jan 2007 07:32
- Location: Сергели->Новосибирск->SFBA->Новосибирск->Москва->NY->SFBA
Re: А был ли мальчик? (помянем плюсы)
У вас классическая задача COW - copy on write. Погуглите на эту тему.ksi wrote: 25 Jan 2018 06:16 Ну произвольная структура какая-то, инстанс какого-то класса. Нважно С или С++. Такая задача, неважно откуда она возникает, это специфическое применения. Потом эти копии будут модифицироваться, слега, ну какое-то поле будет подправлено. Мой опыт, что модификация занимает в сотни раз меньше времени, чем отведение памяти под объект, поэтому и вопрос. Надо сэкономить на копировании.
Насколько я помню Windows это вовсю использует для работы с памятью.
Спи быстрее, твоя подушка нужна другому. Copyright Зощенко
-
- Уже с Приветом
- Posts: 3003
- Joined: 14 Apr 2004 01:11
- Location: SFBA (было: Минск, Беларусь)
Re: А был ли мальчик? (помянем плюсы)
Если погрузиться глубже уровня С++ платформы, то в системах с виртуальной памятью вы можете достичь такого эффекта заполнив копиями вашего объекта всего одну физическую страницу памяти и замапив эту единственную страницу в требуемый вам диапазон виртуальных адресов адресного пространства процесса. То есть пока вы используете этот диапазон адресов только по чтению, вы будете видеть в нем виртуальные копии одной и той же физической страницы: гигантский массив копий, на построение которого вы затратили минимальные усилия.ksi wrote: 25 Jan 2018 05:37 А можно unrelated вопрос? У меня была такая ситуация (я не программист в чистом виде, поэтому сорри, если чего не понимаю): мне нужно создать в памяти копии какого объекта. В большом количестве, сотни тысяч или миллионы потенциально. Поинтеры на новые объекты куда-то положить, ну в массив например. Есть какой-нибудь трюк чтобы это сделать наиболее быстро или ничего кроме цикла из memcpy нельзя придумать?
При необходимости записи будет работать механизм copy-on-write, т.е. при записи в некую точку этого диапазона виртуальных адресов от исходной физической страницы "на лету" будет отпочковываться новая физическая страница, в которой и будет выполняться модификация. Понятно, что если в конечном итоге вы собираетесь модифицуировать все элементы вашего гигантского массива, то "отпочкуется" в итоге все: финальный эффект не будет отличаться от изначального физического выделения и явного заполнения всего массива...
Best regards,
Андрей
Андрей
-
- Уже с Приветом
- Posts: 803
- Joined: 24 Jan 2007 07:32
- Location: Сергели->Новосибирск->SFBA->Новосибирск->Москва->NY->SFBA
Re: А был ли мальчик? (помянем плюсы)
На этот случай есть std::deque.ksi wrote: 25 Jan 2018 14:17 А память под вектор выделяется одним куском или она может быть фрагментирована? Это можно как-то эмулировать в С стиле: я имею в виду, что если просто звать malloc (1000000*sizeof (MyObject)) то такого куска памяти подряд может просто не быть. У вектора есть внутренняя поддержка для таких ситуаций?
Спи быстрее, твоя подушка нужна другому. Copyright Зощенко
-
- Уже с Приветом
- Posts: 803
- Joined: 24 Jan 2007 07:32
- Location: Сергели->Новосибирск->SFBA->Новосибирск->Москва->NY->SFBA
Re: А был ли мальчик? (помянем плюсы)
del
Спи быстрее, твоя подушка нужна другому. Copyright Зощенко
-
- Уже с Приветом
- Posts: 19041
- Joined: 11 Jan 2012 09:25
- Location: CA
Re: А был ли мальчик? (помянем плюсы)
То есть вы не просто "страшный", вы еще и спорить любите ?Prosche wrote: 25 Jan 2018 16:08 Хорошо, хотите натягивать мув на свап, не смею вам мешать. Я сделал все что мог.
Хотите думать, что мув придуман чтобы сохранять дорогие ресурсы, барабан вам на шею. Будете сидеть в тишине вашего кабинета, попробуйте подумать почему именно мув, такое странное название, в словарик там посмотрите. Может быть осознаете простую истину, что идея мув в мув, взять справа и передвинуть влево, а совсем не сохранить "дорогие ресурсы".
https://www.youtube.com/watch?v=wOwblaKmyVw