Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Что происходит при вызове std::move? / 21 сообщений из 21, страница 1 из 1
12.11.2015, 07:51
    #39101351
log_here
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
Как связан
Код: sql
1.
std::move

с
Код: sql
1.
SomeType(SomeType&& )

и с
Код: sql
1.
operator = (SomeType&& )

?
Правильно ли я понял, что при std::move меняется только оболочка?
Верно ли, что здесь вызывается конструктор копирования && и оператор присваивания && соответственно?
Код: sql
1.
2.
3.
4.
5.
6.
  
SomeType x;
SomeType y;
SomeType type = std::move(x);       // конструктор SomeType(SomeType&& ) 
y = std::move(x);                          // operator = (SomeType&& )
 



Почему не устраивал
Код: sql
1.
std::swap?
...
Рейтинг: 0 / 0
12.11.2015, 09:42
    #39101430
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
log_here,

Не знаю ответа ни на один твой вопрос, но подозреваю, что разница тупо в том, что один (новый) подразумевает move semantics, а другой -- наоборот, о ней ничего не знает.
...
Рейтинг: 0 / 0
12.11.2015, 15:52
    #39101980
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
log_hereПочему не устраивал
Код: sql
1.
std::swap?


std::move(x) - это просто преобразование типа, никакую конкретную операцию он не делает.
Конкретика будет зависеть от того поддерживает ли приемник семантику перемещения.
Если не поддерживает, то данные скопируются.
Если поддерживает, то данные переместятся (в смысле быстрее чем копирование).
Т.е. вы можете изначально не реализовывать перемещение. А в будущем - реализовать, не переписывая код использующий класс.

А в случае swap нужно во-первых сразу реализовать метод swap, что для вложенных структур довольно муторно, во-вторых само название не соответствует тому что мы хотим сделать, т.е. код становится менее читаемым.
...
Рейтинг: 0 / 0
14.11.2015, 13:10
    #39103410
alexy_black
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
std::move преобразовывает lvalue to rvalue, вот и все :)
то есть если у объекта принимающего из std::move есть консрутор перемещения, то он сработает и в перемещаемомо объекте останется мусор.

как работет.. я подозреваю, что это просто способ компилятору указать что это rvalue.. то есть оболочка для какой-то внутренней штуки, но она стандартиризированная.. не проверял.
...
Рейтинг: 0 / 0
14.11.2015, 14:13
    #39103439
wst
wst
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
У std::move(o) внутре static_cast<T&&>(o). То есть, конечно чуть посложнее, но сводится именно к этому.
...
Рейтинг: 0 / 0
14.11.2015, 15:45
    #39103489
mcureenab
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
alexy_blackstd::move преобразовывает lvalue to rvalue, вот и все :)
Я так понимаю, метод предназначен для поддержки смены владельца объекта.
В терминах UML у объекта может быть владелец, который обязан его уничтожить, когда он больше не нужен. Объект без хозяина, это вообще говоря ошибка, которая приводит к утечке памяти.
...
Рейтинг: 0 / 0
14.11.2015, 16:20
    #39103510
alexy_black
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
нет..
есть объект, размещенный в автоматической памяти. он исчезен как только выйдет из области видимости... то есть
Код: plaintext
1.
2.
3.
4.
{
    int i;
    // do something
} // i destroys here



и есть объекты, размещенные в кучи. они удаляться от туда только если вызвать delete
Код: plaintext
1.
2.
3.
4.
5.
{
   int *i_ptr = new int();
   int *other_ptr = new int();
   delete other_ptr; // other_ptr destroys here
}

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


std::move просто перемещает объект.. не владение, это не rust. то есть foo=std::move(bar) вызовет foo.operator = (foo_type&& other) и все. этот опрератор может оставить в other мусор, им уже никто не воспользуется (или пожалеет об этом).
...
Рейтинг: 0 / 0
14.11.2015, 18:09
    #39103574
YesSql
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
alexy_black foo=std::move(bar) вызовет foo.operator = (foo_type&& other) и все. этот опрератор может оставить в other мусор, им уже никто не воспользуется (или пожалеет об этом).
уточню. как анатолий заметил выше может вызваться или

Код: plaintext
1.
foo.operator = (foo_type&& other)

или
Код: plaintext
1.
foo.operator = (foo_type& other)

в зависимости от того можно ли к bar применить перемещение или нет.
...
Рейтинг: 0 / 0
25.10.2016, 08:12
    #39333232
CEMb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
А у меня ещё вопрос.
Вот я смотрю мсдн , там в перемещающем конструкторе надо по-хорошему обнулять данные входящего объекта. Это получается дороже, чем просто его скопировать. Т.о. в общем случае конструктор перемещения прироста не даёт? Т.е. в случае, как со строкой, swap?

И ещё вопрос по 11-м плюсам.
Смотрю в асм, там при создании объекта появилась функция __autoinitclass2, в которой забивание памяти 0xcc, обычным способом, а потом делается memset его же нулями... Объясните кто-нибудь логику данного действа?
А потом зовётся конструктор, и в нём опять забивание памяти by 0xcc. Мне кажется, я что-то не так понял...
...
Рейтинг: 0 / 0
25.10.2016, 08:25
    #39333234
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
Новое в С++ 11 и 14 достаточно подробно расписано в книге Эффективный и современный С++
...
Рейтинг: 0 / 0
25.10.2016, 11:26
    #39333380
CEMb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
Dima TНовое в С++ 11 и 14 достаточно подробно расписано в книге Эффективный и современный С++ ну вот по её мотивам я и полез в мсдн посмотреть. Так какой ответ на первый вопрос?
...
Рейтинг: 0 / 0
25.10.2016, 12:30
    #39333478
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
Я так понял что это какая-то магия во время компиляции
5.1. Азы std::move и std::forward Полезно подойти к std::move и std::forward с точки зрения того, чего они не делают. std: :move ничего не перемещает. std: : forward ничего не передает. Во время выполнения они не делают вообще ничего. Они не генерируют выполнимый код - ни одного байта.
...
Т.е. реально в коде ничего не копируется. Точнее еще ряд условий в коде надо соблюсти чтобы это работало. В книжке подробно описано. Я не пользуюсь этим. У меня в основном код в стиле С с классами.
...
Рейтинг: 0 / 0
25.10.2016, 12:49
    #39333505
Siemargl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
CEMbА у меня ещё вопрос.
Вот я смотрю мсдн , там в перемещающем конструкторе надо по-хорошему обнулять данные входящего объекта. Это получается дороже, чем просто его скопировать. Т.о. в общем случае конструктор перемещения прироста не даёт? Т.е. в случае, как со строкой, swap?

И ещё вопрос по 11-м плюсам.
Смотрю в асм, там при создании объекта появилась функция __autoinitclass2, в которой забивание памяти 0xcc, обычным способом, а потом делается memset его же нулями... Объясните кто-нибудь логику данного действа?
А потом зовётся конструктор, и в нём опять забивание памяти by 0xcc. Мне кажется, я что-то не так понял...Это скорее всего для отлова ошибок при отладке. Смотри релизный вариант.

::move() это продолжение линии оптимизаций типа RVO
...
Рейтинг: 0 / 0
25.10.2016, 12:52
    #39333509
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
Я так понял это перемещение впилено в STL, чтобы избавиться от копирования в случаях типа
Код: plaintext
1.
2.
3.
4.
vector<my_type_t> v;
...
my_type_t x = ....;
v[i] = x;


Как я понял: в реале не выделяется память под x, а сразу пишется в v[i], за счет этого становиться быстрее, т.к. на одно копирование меньше.
...
Рейтинг: 0 / 0
25.10.2016, 13:49
    #39333558
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
CEMbВот я смотрю мсдн , там в перемещающем конструкторе надо по-хорошему обнулять данные входящего объекта. Это получается дороже, чем просто его скопировать.
Во-первых надо не обнулять, а оставлять в любом консистентном состоянии.
Проще всего это сделать swap между исходным и конечным объектом.
Во-вторых, не знаю с чего вы решили что это дороже копирования.
Когда в объекте есть динамическая память, то перемещение всегда быстрее чем копирование.
...
Рейтинг: 0 / 0
25.10.2016, 14:22
    #39333593
Siemargl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
Anatoly Moskovsky,

Точнее, когда в объекте есть ссылки на подобъекты
...
Рейтинг: 0 / 0
25.10.2016, 14:22
    #39333595
NekZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
alexy_blackstd::move преобразовывает lvalue to rvalue, вот и все :)
то есть если у объекта принимающего из std::move есть консрутор перемещения, то он сработает и в перемещаемомо объекте останется мусор.

как работет.. я подозреваю, что это просто способ компилятору указать что это rvalue.. то есть оболочка для какой-то внутренней штуки, но она стандартиризированная.. не проверял.
[captain obvious mode]
Если кто читал Мейерса, там чёрным по белому написано, что std::move лишь приводит значение к rvalue. И, кстати, не имеет смысла его применять к POD-типам. std::move никак объект сам не меняет. Это делает уже move ctor или move operator=, это в их власти сделать объект невалидным/оставить его как есть/обнулить и т. д. Принципиально-то на бинарном уровне ничего не поменялось, это просто дополнительная семантика, применяя которую, можно без особого труда "перемещать" ресурсы тяжеловесных объектов. move мемберы лишь "отцепляют" владение внутренними данными от старого объекта и прицепляют к текущему. Обычно это достигается присваиванием указателей на тяжеловесные данные/ресурсы, и обнулением их в старом объекте (rvalue). Просто меняется владелец.
[/captain obvious mode]
...
Рейтинг: 0 / 0
25.10.2016, 20:31
    #39333934
СЕМЬ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
SiemarglCEMbСмотрю в асм, там при создании объекта появилась функция __autoinitclass2, в которой забивание памяти 0xcc, обычным способом, а потом делается memset его же нулями... Объясните кто-нибудь логику данного действа?
А потом зовётся конструктор, и в нём опять забивание памяти by 0xcc. Мне кажется, я что-то не так понял...Это скорее всего для отлова ошибок при отладке. Смотри релизный вариант.
Ага, это-то понятно, вопрос был про зачем два раза, да ещё и обнулять...
Siemargl::move() это продолжение линии оптимизаций типа RVO
Вот с RVO я не понял... как я ни пытался, у меня не получилось сделать move локальной переменной в переменную, которая была создана до вызова функции, т.е. не конструктор. Сначала по ошибке делал return std::move(), потом вчитался, убрал, не помогло, потом совсем вчитался... и как сделать мув-то? У меня в любом случае в этой точке вызывался конструктор, потом деструктор, хотя оба правила соблюдались.

Anatoly MoskovskyCEMbВот я смотрю мсдн , там в перемещающем конструкторе надо по-хорошему обнулять данные входящего объекта. Это получается дороже, чем просто его скопировать.
Во-первых надо не обнулять, а оставлять в любом консистентном состоянии.
Проще всего это сделать swap между исходным и конечным объектом.
я привёл ссылку на мсдн, обнулять было про то, что там написано. Общие правила
SiemarglВо-вторых, не знаю с чего вы решили что это дороже копирования.
Когда в объекте есть динамическая память, то перемещение всегда быстрее чем копирование.
Никто не читает, что я пишу я написал "в общем случае". И привёл ссылку на мсдн, как ещё одно подтверждение. Потому что:
NekZИ, кстати, не имеет смысла его применять к POD-типам
И я же там же написал про swap у строк

PS: а так я попробовал move-семантику, довольно прикольно оно всё работает. Вот то, что я привёл из мсдн-а, мне явно нигде делать не пришлось.
Чуть ранее, когда я не вчитался, я во многих местах в мув-конструкторах просто поставил std::move входящей ссылки... и это правильно отработало. Потом я заменил на *this = incoming. И тоже всё правильно отработало (перемещающие операторы у меня были описаны). Т.е. у меня в переменных классов были строки и параметры шаблонов. Кстати, там Мейерс делает замечание про шаблоны, что не смотря на шаблон, входящий параметр мув-конструкторов не является универсальной ссылкой. Вроде как очевидно, но я чуть не влетел и не написал std::forward
Такие дела
...
Рейтинг: 0 / 0
26.10.2016, 22:55
    #39334852
alexy_black
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
NekZalexy_blackstd::move преобразовывает lvalue to rvalue, вот и все :)
то есть если у объекта принимающего из std::move есть консрутор перемещения, то он сработает и в перемещаемомо объекте останется мусор.

как работет.. я подозреваю, что это просто способ компилятору указать что это rvalue.. то есть оболочка для какой-то внутренней штуки, но она стандартиризированная.. не проверял.
[captain obvious mode]
Если кто читал Мейерса, там чёрным по белому написано, что std::move лишь приводит значение к rvalue.
[/captain obvious mode]ну, так и я о чем и говрою :)

просто если вызвать foo foo_var(other_foo_var); то будет вызван констрктор копирования. если сказать foo foo_var(std::move(other_foo_var)) - перемещения. в результате other_foo_var нельзя уже будет использовать.
...
Рейтинг: 0 / 0
27.10.2016, 10:24
    #39335036
NekZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
alexy_blackпросто если вызвать foo foo_var(other_foo_var); то будет вызван констрктор копирования. если сказать foo foo_var(std::move(other_foo_var)) - перемещения. в результате other_foo_var нельзя уже будет использовать.
Это зависит от того что сделает конструктор перемещения с перемещаемым объектом. Как я уже сказал выше, он может и ничего не сделать. Ты заставил меня пойти на ideone и налабать этот пример
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
#include <iostream>
using namespace std;

class A
{
public:
	struct data
	{
		int a;
		double f;
		std::string s;
	};
	
	A() : d{ 2, 4.0, "Foo" }
	{
	}
	
	A( A && other )
	: d( other.d )
	{
		// Именно здесь мы и можем сделать объект невалидным, закинуть в него "мусор".
		// Но никто такого делать не будет
		other.d.s = "None";
		other.d.a = 0;
	}
	
	void out()
	{
		cout << d.a << " " << d.f << " " << d.s << endl; 
	}
	
private:
	data d;
};


int main() {
	A a;
	A a1(std::move(a));
	a.out();
	a1.out();
	return 0;
}


stdout:
0 4 None
2 4 Foo

И как видишь, объект A a всё ещё можно использовать ;-) Это просто конвенция того, что должен делать move ctor, не верь слухам что там "мусор" оказывается.
...
Рейтинг: 0 / 0
30.10.2016, 19:39
    #39337387
alexy_black
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что происходит при вызове std::move?
NekZ,

ну, это понятно.. можно вообще вместо перемещения сделать обычный копирующий конструктор. но!
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
class foo{
  struct details {
    std::string str;
    void do(){std::cout << str << std::endl;}
  };

  std::unique_ptr pimpl_;
  details* pimpl() {return pimpl_.get();}
  const details* pimpl() const {return pimpl_.get();}
public:
  foo(const foo&)=delete;
  foo& operator = (const foo&)=delete;
 
  foo(foo&& other) : pimpl_(std::move(other.pimpl_)) {}
  foo& operator = (foo&& other) {pipml_ = std::move(other.pimpl_);return *this;}

  foo() : pimpl_(new details()) {}
  ~pimpl() noexcept {}

  void do_somethis() {
    assert( pimpl_ );
    pimpl()->do();
  }
};

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

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

вот например даже елси класс сам написал, потом в коде где-нибудь его использовал после перемещения, а потом, через много времени, решил немного оптимизировать конструктор перемещения, то тот код может и провалится.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Что происходит при вызове std::move? / 21 сообщений из 21, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]