LINUX.ORG.RU

C++ std::move

 ,


0

3

Такой глупый вопрос. Есть небольшой код:

std::string s1 = "s1";
std::string s2 = "s2";
s2 = std::move(s1);

Почему move работает как swap? То есть в конце значения такие: s2=«s1», s1=«s2». Я ожидал, что будут: s2=«s1», s1="". Использую gcc 4.9.


Потому что использование s1 после перемещения – UB

Stil ★★★★★
()

Это не move работает как swap, а operator=(string &&s) работает через swap. Это распространённый способ.

uuwaan ★★
()

Когда вы уже читать научитесь.

Unless otherwise specified, all standard library objects that have been moved from are placed in a valid but unspecified state. That is, only the functions without preconditions, such as the assignment operator, can be safely used on the object after it was moved from:

anonymous
()

Потому что это эффективная реализация, а значения у «moved from» объекта неспецифицированно, т.е. std::swap вполне себе валидная реализация. Но использовать s1 после перемещения из него не надо всё равно, его можно либо разрушить, либо переприсвоить (ну и что-нибудь ещё, если указано отдельно для какого-то класса).

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

Потому что это эффективная реализация, а значения у «moved from» объекта неспецифицированно, т.е. std::swap вполне себе валидная реализация.

Вот за такие трюки Си++ и должен бы умереть.

tailgunner ★★★★★
()
Ответ на: комментарий от xaizek

Спасибо! Понятна теперь их логика! Для чего делать дополнительное обнуление, если старое значение все равно больше не нужно.

silart
() автор топика
Ответ на: комментарий от tailgunner

Вот за такие трюки Си++ и должен бы умереть.

это ты брось!

silart
() автор топика
Ответ на: комментарий от tailgunner

А альтернатив подобным трюкам особо нет. Либо так, либо урезать язык и связывать руки разработчикам, чтобы проверку мог выполнить компилятор, как это сделано в rust. И утверждать, что второе однозначно лучше, я бы не стал, так как тогда сразу появляются методы компенсации этих ограничений, которые сами очень походят на костыли (правда, они более явные).

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

А альтернатив подобным трюкам особо нет

Есть. Как минимум - рекомендация оставлять moved-out объект в гарантированно невалидном состоянии, когда попытка использовать его ведет к сегфолту.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

рекомендация оставлять moved-out объект в гарантированно невалидном состоянии, когда попытка использовать его ведет к сегфолту.

Вызов деструктора при выходе из области видимости — тоже использование. Как-то ты узко смотришь.

i-rinat ★★★★★
()
Ответ на: комментарий от tailgunner

Это не всегда можно сделать. Может там int поле публичное. Да и пихать генерацию сегфолта во все геттеры тот ещё вариант, который сильно повлияет на их встраивание и следом на производительность. Также маленьким объектам нужен будет отдельный флаг, что будет увеличивать их размер и сделает не такими уж и маленькими. Стандартное решение должно быть с минимальными дополнительными расходами и я думаю, они такое искали, но не нашли ничего толкового.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

Это не всегда можно сделать

Проблема в том, что этого сознательно не делают даже тогда, когда это можно сделать. ЗАТО СКОРОСТЬ!!!!1

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

А ты не видишь очевидного.

Опять эта напускная загадочность. Чтобы понять, о чём речь, нужно из тебя информацию клещами вытягивать.

i-rinat ★★★★★
()
Ответ на: комментарий от tailgunner

что этого сознательно не делают даже тогда, когда это можно сделать. ЗАТО СКОРОСТЬ!!!!1

В LLVM есть своя реализация optional. В отладочной версии, если функция возвращает optional, а ты его не проверил, взял значение просто так, программа падает на assert'е.

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

i-rinat ★★★★★
()

По моему крутая реализация, таким образом нужен лишь деструктор, который поддерживает очистку валидного состояния и move должен оставять другой обьект в таком валидном состоянии (неопределенном). Это проще чем встраивать в язык флажки или что-то подобное.

vertexua ★★★★★
()
Ответ на: комментарий от tailgunner

Нет. Просто разработчик на C++ должен уметь сказать что делает каждая функция в его коде. Если он этого не умеет, то он не разработчик на C++.

peregrine ★★★★★
()
Ответ на: комментарий от tailgunner

К C++ одно единственное требование - скорость. Если тебе скорость не важна, то бери C#, Java, что-то там ещё.

peregrine ★★★★★
()
Ответ на: комментарий от peregrine

Просто разработчик на C++ должен уметь сказать что делает каждая функция в его коде. Если он этого не умеет, то он не разработчик на C++.

Я знал, что здесь обязательно появится кто-то с предсказуемыми дешевыми понтами. Я не ошибся.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

Жаль тебя расстраивать, но это не чушь, а если чушь, то обоснуй. Всякие C#, Java, которые гораздо меньше способов явного выстрела в ногу предоставляют медленнее из-за этого и не годятся, например, в разработке быстрых игровых движков (сейчас поклонники тормозного Unity набегут, но я им напомню что на C# там написана только та часть, где не требуется производительность, а важный код по прежнему на C++).

peregrine ★★★★★
()
Ответ на: комментарий от peregrine

Жаль тебя расстраивать

Твое мнение меня совершенно не расстроит.

обоснуй

Скорость (скорость работы результирующей программы) никогда не является единственным требованием к ЯП. Обосновывать это я, естественно, не стану.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

Обосновывать это я, естественно, не стану.

С тобой всё ясно. То что всегда тебе приходится идти на компромиссы при разработке ПО (да и вообще по жизни), ты не замечаешь. Например у тебя в ЯП следующие основные критерии (надеюсь ничего не забыл): скорость разработки, скорость результирующей программы, простота разработки, стабильность и безопасность приложения, стоимость разработки, умение коллектива разработчиков. Вот когда у тебя главенствует по приоритетам скорость результирующей программы и программа сложная и большая, то есть смысл выбрать C++ в качестве языка разработки. В противном случае использование C++ не обосновано.

peregrine ★★★★★
()
Ответ на: комментарий от peregrine

С тобой всё ясно

Окей.

То что всегда тебе приходится идти на компромиссы при разработке ПО (да и вообще по жизни), ты не замечаешь

Да? Ну... окей снова.

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

Хм. Совсем недавно скорость была единственным требованием.

и программа сложная и большая

И тогда же надо было уметь сказать, что делает каждая функция.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Не понял, причем здесь отладочная версия.

Потому что код, который делает проверку, обёрнут в проверку макроса NDEBUG.

i-rinat ★★★★★
()
Ответ на: комментарий от tailgunner

И тогда же надо было уметь сказать, что делает каждая функция.

Да. Это надо всегда, иначе потом получится что-то неподдерживаемое и неюзабельное. Я не говорю, что по памяти, хотя помнить все из стандартной библиотеки надо.

peregrine ★★★★★
()
Ответ на: комментарий от tailgunner

Вот за такие трюки Си++ и должен бы умереть.

Это ещё почему? Другое дело, что было бы здорово, чтобы компилятор контролировал, что с перемещёнными объектами не делают ничего неположенного, но это из области фантастики.

DarkEld3r ★★★★★
()
Ответ на: комментарий от peregrine

Я не говорю, что по памяти, хотя помнить все из стандартной библиотеки надо.

Ты всерьёз говоришь, что помнишь всё-всё из стандартной библиотеки? Со всеми нюансами и тонкостями?

DarkEld3r ★★★★★
()
Ответ на: комментарий от anonymous

а к статическим анализаторам.

Они смогут только самые простые варианты отследить. А если это член класса, например, то кто его знает - будет оно использоваться потом или нет.

anonymous
()
Ответ на: комментарий от peregrine

Я не говорю, что по памяти, хотя помнить все из стандартной библиотеки надо.

А ты все помнишь? Серьезно?

Dudraug ★★★★★
()
Ответ на: комментарий от anonymous

Это не к компилятору, а к статическим анализаторам.

Не вижу ничего плохого (даже наоборот) в переносе проверок в компилятор. Но в данном конкретном случае, даже статический анализатор не всегда поможет.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Это ещё почему?

Потому что UB должно быть сведено к минимуму. И поощрение использования UB во имя мифических выигрышей по скорости - идиотизм. Я думал, это очевидно.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Я думал, это очевидно.

Тут проблема в том, что твои комментарии далеко не всегда очевидны. Касательно UB согласен, но акценты я (бы) расставил по другому.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

твои комментарии далеко не всегда очевидны

Если это и это не очевидно, то я уже и не знаю, как высказываться.

акценты я (бы) расставил по другому

Как?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Если это и это не очевидно, то я уже и не знаю, как высказываться.

Так второй комментарий - это именно необходимое уточнение, которое последовало не сразу. Так что достаточно заканчивать мысль, а не напускать туману.

Как?

Как уже сделал выше: проблема не в самом перемещение и реализации присваивания (ведь отвечал ты именно на это), а в том, что дальнейшую жизнь «перемещённого» объекта никто не контролирует, кроме самого программиста.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Все основное, а когда используешь и не помнишь нюансы и тонкости, то не ленись читать что используешь.

peregrine ★★★★★
()
Ответ на: комментарий от DarkEld3r

проблема не в самом перемещение и реализации присваивания (ведь отвечал ты именно на это)

Нет. Проблема не в перемещении или отсутствии контроля со стороны компилятора, а в том, что поощряется ублюдочный стиль попыток набрать миллиграмм скорости за счет UB. Т.е. проблема не техническая - проблема в головах. Проблема в сообществе, культивирующем подобный подход и состоящем из персонажей вроде отписавшихся в этом топике. Демоны скорости, епт.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

перемещение - это «кража» внутренних данных из (целевое использование) rvalue reference. Логично, что обокраденный объект остаётся в неопределённом состоянии. Автор топика украл данные из lvalue, что не совсем то, для чего && и move были сделаны. Так отчего же ты негодуешь?

P.S. Хотя многочисленные UB в стандарте я тоже очень не люблю. В жабе такого нет, и почему-то она по скорости обработки данных к С++ близка вплотную. Видимо, UB - это экономия на спичках.

former_anonymous ★★★
()
Последнее исправление: former_anonymous (всего исправлений: 1)
Ответ на: комментарий от former_anonymous

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

Только в синтетических тестах и бенчмарках. На реальном рабочем коде и данных Java выглядит не так хорошо.

anonymous
()
Ответ на: комментарий от former_anonymous

UB - это явно не то, из-за чего C++ быстрее.

Кокрастыке наоборот. Оптимизаторы любят выкидывать половину твоего кода, если там есть UB.

anonymous
()
Ответ на: комментарий от anonymous

UB - это явно не то, из-за чего C++ быстрее.

Кокрастыке наоборот

Бред. Выигрыш составляет единицы процентов на микробенчмарках.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

Очередной вскукарек рустера...

А ты быстро слился :/

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Че-то тебя несет. В комитете сидят опытные люди с реальными проблемами, а не демоны. Что делает move - везде четко написано, кто виноват тем кто доки не читает. А ничего страшного, кстати, он не делает, технически это и не UB.

И вообще непонятно, что предлагаешь ты. Считай что это и есть невалидное состояние с вероятностью сегфолта, а гарантировать его нереально.

anonymous
()
Ответ на: комментарий от tailgunner

Как минимум - рекомендация оставлять moved-out объект в гарантированно невалидном состоянии, когда попытка использовать его ведет к сегфолту.

Ну-ка, рустер, расскажи, как в рамках модели памяти и абстрактной машины, описанной в стандарте, описать сегфолт.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.