Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
anti-k
227 / 75 / 31
Регистрация: 17.07.2015
Сообщений: 774
Завершенные тесты: 1
1

Поясните по move конструктору

14.02.2016, 12:13. Просмотров 984. Ответов 6
Метки нет (Все метки)

У меня есть такой вот конструктор, который получает на вход мултимап из парсера, в дальнейшем он ненужен.
Как правильно прописать мув конструктор?
C++
1
Store(const multimap<string, shared_ptr<Tovar>>&ob) :res(ob) {}
Такой вариант?
C++
1
Store(multimap<string, shared_ptr<Tovar>>&&ob) :res(ob) {}
вопрос умрет ли shared_ptr или как его убить?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.02.2016, 12:13
Ответы с готовыми решениями:

Вопрос по конструктору
задали задание: конструктор, позволяющий создавать строку произвольного...

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

Как инит масс, передава указатель конструктору?
#include &lt;iostream&gt; #include &lt;string&gt; using namespace std; class swapall...

Передать инициализированный std::vector конструктору базового класса
В общем появилась одна проблема. Никак не пойму как можно сделать. В общем дело...

Запретить initializer-list конструктору принимать rvalue значения/ссылки
Здравствуйте! Опишу проблему из заголовка поста на примере... Допустим есть...

6
hoggy
Нарушитель
Эксперт С++
7087 / 3130 / 648
Регистрация: 15.11.2014
Сообщений: 7,209
Завершенные тесты: 1
14.02.2016, 12:21 2
Лучший ответ Сообщение было отмечено Nick Alte как решение

Решение

Цитата Сообщение от anti-k Посмотреть сообщение
Как правильно прописать мув конструктор?
C++
1
2
3
Store( multimap<string, shared_ptr<Tovar> >&& ob) 
    :res(  std::forward< multimap<string, shared_ptr<Tovar> > >(ob) ) 
{}
Цитата Сообщение от anti-k Посмотреть сообщение
вопрос умрет ли shared_ptr или как его убить?
нет. после опустошения, он будет в состоянии uncpecified.
что означает - валиден, и работоспособен.
но точно не известно в каком.

он умрет на общих основаниях,
когда завершится время его жизни.
3
DrOffset
8146 / 4726 / 1155
Регистрация: 30.01.2014
Сообщений: 7,701
14.02.2016, 12:52 3
Добавлено через 30 минут
Цитата Сообщение от hoggy Посмотреть сообщение
C++
1
2
3
Store( multimap<string, shared_ptr<Tovar> >&& ob) 
    : res(  std::forward< multimap<string, shared_ptr<Tovar> > >(ob) ) 
{}
Все-таки в этом случае нужно использовать std::move. Т.к. здесь однозначно подразумевается rvalue-ccылка, а не deduced type.

anti-k, вот здесь есть доклад Скотта Мейрса на тему этих различий: https://channel9.msdn.com/Shows/Goin...ences-in-Cpp11
2
hoggy
Нарушитель
Эксперт С++
7087 / 3130 / 648
Регистрация: 15.11.2014
Сообщений: 7,209
Завершенные тесты: 1
14.02.2016, 12:59 4
Цитата Сообщение от DrOffset Посмотреть сообщение
Все-таки в этом случае нужно использовать std::move. Т.к. здесь однозначно подразумевается rvalue-ccылка, а не deduced type.
с точки зрения иллюстрации намерений - да.
однако, std::forward более универсален,
и живуч в плане изменений.

c std::move можно влететь,
если намерения изменятся,
а его поправить забудут.

std::forward корректно сработает в любом случае.
0
DrOffset
8146 / 4726 / 1155
Регистрация: 30.01.2014
Сообщений: 7,701
14.02.2016, 13:23 5
Цитата Сообщение от hoggy Посмотреть сообщение
std::forward более универсален
Это его достоинство и одновременно недостаток.
Давай сразу расставим точки над i, мой пост не нацелен на обличение тебя в чем-либо. Я прекрасно понимаю, что ты в курсе различий. В данном случае я забочусь исключительно о ТС. Потому что наши с тобой недосказанности он может воспринять неправильно.

Все, что ниже, предназначено для ТС:
Итак,
std::move всегда выполняет приведение к rvalue. И используется в контекстах, когда rvalue точно должно быть. Один из таких контекстов - это move-конструктор.
std::forward приводит свой аргумент к rvalue только тогда, когда аргумент связан с rvalue. Он используется в контекстах, когда мы работаем с так называемым deduced type (Скотт Мейерс такое использование && обозвал universal reference).
Для закрепления материала рекомендую почитать главу 5 в новой книжке Мейeрса (Effective Modern C++), там описаны как различия, так и рекомендации применения std::move и std::forward.
4
hoggy
Нарушитель
Эксперт С++
7087 / 3130 / 648
Регистрация: 15.11.2014
Сообщений: 7,209
Завершенные тесты: 1
14.02.2016, 14:01 6
Лучший ответ Сообщение было отмечено gru74ik как решение

Решение

Цитата Сообщение от DrOffset Посмотреть сообщение
Давай сразу расставим точки над i
есть ещё один момент, который выносит мозг.

для всех желающих:

некоторые спрашивают:
зачем вообще нужен std::move?

во времена с++03 временный объект - тупо безымянный:
C++
1
make_obj().work(); //у временного объекта нет имени
не всем очевидно, что с тех пор в этом плане
так ничего и не изменилось.

начиная со времен с++11, стандарт узаконил особый тип данных:
rvalue reference, суть которого - ссылка на временный объект.

и вот здесь могут возникать недопонимания.
рассмотрим код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
// казалось бы, функция должна 
// принимать объекты указанного типа
void foo(some&&){ ...}
 
...
 
some obj;
 
some&& pv = std::move(obj);
 
// error: cannot bind ‘some’ lvalue to ‘some&&’
// ан нет, не принимает
foo(pv);
оказывается, параметр функции rvalue-reference
в качестве аргумента принимает только и только временные объекты.

но сам по себе тип данных "rvalue-reference" вовсе не означает,
что связанный с ним объект - временный.

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

временными могут быть только и только безымянные объекты.

их ещё называют prvalue (pure rigth value),
или "чистые", "настоящие", "истинные" временные объекты.

все что делает std::move - возвращает безымянный rvalue-reference.
то есть, настоящий временный объект (prvalue)
и вот такой результат её работы действительно
считается компилятором ссылкой на временный объект.

http://rextester.com/GIVTG55539

C++
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
#include <iostream>
 
struct sample
{
    sample(){}
    
    sample(sample&& ) { std::cout <<"yes\n"; }
};
 
 
void foo(sample&& rv)
{
    // не работает, попытка вызвать конструктор копии
    //sample s(rv);
    
    // конструктор временных объектов работает 
    // только и только с временными объектами
    // временный объект должен быть безымянным
    sample s( std::move(rv) );
}
 
int main()
{
    std::cout << "Hello, world!\n";
    
    sample obj;
    
    sample&& rv = std::move(obj);
    
    // error: cannot bind ‘sample’ lvalue to ‘sample&&’
    // принимает только временные объекты
    // а временные объекты обязаны быть безымянными
    //foo( rv );
    
    foo( std::move(rv) );
}
7
rat0r
36 / 43 / 9
Регистрация: 16.02.2018
Сообщений: 260
22.04.2018, 01:52 7
Цитата Сообщение от hoggy Посмотреть сообщение
все что делает std::move - возвращает безымянный rvalue-reference.
то есть, настоящий временный объект (prvalue)
Выражение std::move(something) — это xvalue (если something имеет тип объекта, а не функции), а не prvalue.
0
22.04.2018, 01:52
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.04.2018, 01:52

Выбор типа переменной-члена класса в зависимости от параметров передаваемых конструктору
Здравствуйте форумчане! Ответьте пожалуйста на вопрос - возможно ли такое на...

std::move()
Есть ли разница между следующими вещами: A = std::move(B); // and...

move семантика
Сейчас стало появляться нечто вроде такого: class X { public: X (const...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru