Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / move- семантика: как передать unique_ptr? / 13 сообщений из 13, страница 1 из 1
01.05.2018, 10:14
    #39638636
AlekseySQL
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
move- семантика: как передать unique_ptr?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
void OpenBinFileForWrite(std::unique_ptr<std::ofstream> File, cstring& FileName);

void WriteArrayToBinFile(const VariativeData& Settings, cstring& NameFile) const
{
             auto File = std::make_unique<std::ofstream>;

            //open file for write
            OpenBinFileForWrite(std::move(File), NameFile);//ОШИБКА!!!
}


Код: plaintext
1.
ошибка: could not convert ‘std::move(File)’ from ‘std::remove_reference<std::unique_ptr<std::basic_ofstream<char> > (*&)()>::type {aka std::unique_ptr<std::basic_ofstream<char> > (*)()}’ to ‘std::unique_ptr<std::basic_ofstream<char> >’
             OpenBinFileForWrite(std::move(File), NameFile);

Я пробовал в функции OpenBinFileForWrite принимать по rvalue- ссылке &&. Но все равно получаю ошибки.
...
Рейтинг: 0 / 0
01.05.2018, 10:47
    #39638639
AlekseySQL
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
move- семантика: как передать unique_ptr?
Если вместо:
Код: plaintext
1.
auto File = std::make_unique<std::ofstream>;



написать:
Код: plaintext
1.
2.
std::ofstream* pFile = new std::ofstream;
std::unique_ptr<std::ofstream> File(pFile);



то все работает. Причем принимающая функция берет хоть по значению, хоть по правой ссылке- работает...

Я правильно понимаю:

Правая ссылка- это точно такая же ссылка, как и левая, только для временных объектов. Поэтому при ее использовании передача управления произойдет не в момент вызова метода OpenBinFileForWrite, а в момент, когда в методе произойдет явная передача управления. В противном случае (прием в методе по значению) при инициализации параметров метода OpenBinFileForWrite сразу произойдет передача управления и старый объект разрушится.

???

p.s. На просторах интернета нет ни одной нормальной русскоязычной информации по правым ссылкам. Все они друг другу противоречат и рассматривают какие- то частности, а не простые, но фундаментальные вопросы, как передача временного значения в функцию.
...
Рейтинг: 0 / 0
01.05.2018, 10:51
    #39638641
NekZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
move- семантика: как передать unique_ptr?
AlekseySQL
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
void OpenBinFileForWrite(std::unique_ptr<std::ofstream> File, cstring& FileName);

void WriteArrayToBinFile(const VariativeData& Settings, cstring& NameFile) const
{
             auto File = std::make_unique<std::ofstream>;

            //open file for write
            OpenBinFileForWrite(std::move(File), NameFile);//ОШИБКА!!!
}


Код: plaintext
1.
ошибка: could not convert ‘std::move(File)’ from ‘std::remove_reference<std::unique_ptr<std::basic_ofstream<char> > (*&)()>::type {aka std::unique_ptr<std::basic_ofstream<char> > (*)()}’ to ‘std::unique_ptr<std::basic_ofstream<char> >’
             OpenBinFileForWrite(std::move(File), NameFile);

Я пробовал в функции OpenBinFileForWrite принимать по rvalue- ссылке &&. Но все равно получаю ошибки.
Ты круглые скобки у make_unique, случаем, не забыл?
...
Рейтинг: 0 / 0
01.05.2018, 11:06
    #39638643
AlekseySQL
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
move- семантика: как передать unique_ptr?
NekZ, спасибо, меня просто подсказка напугала (после ввода круглых скобок я получал подчеркивание и подсказку "слишком мало параметров"). Так работает.
...
Рейтинг: 0 / 0
01.05.2018, 11:10
    #39638645
NekZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
move- семантика: как передать unique_ptr?
AlekseySQL,

А вот напиши ты тип явно std::unique_ptr<std::ofstream>, то сразу бы понял в чём ошибка ;-) В этом недостаток auto, так что будь внимателен, когда используешь его.
...
Рейтинг: 0 / 0
01.05.2018, 11:19
    #39638648
AlekseySQL
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
move- семантика: как передать unique_ptr?
AlekseySQLЯ правильно понимаю:

Правая ссылка- это точно такая же ссылка, как и левая, только для временных объектов. Поэтому при ее использовании передача управления произойдет не в момент вызова метода OpenBinFileForWrite, а в момент, когда в методе произойдет явная передача управления. В противном случае (прием в методе по значению) при инициализации параметров метода OpenBinFileForWrite сразу произойдет передача управления и старый объект разрушится.

???

Теперь я все понял!

Так работает:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
void OpenBinFileForWrite(std::unique_ptr<std::ofstream>&& File, cstring& FileName);
void WriteArrayToBinFile(const VariativeData& Settings, cstring& NameFile) const
{
             auto File = std::make_unique<std::ofstream>;

            //open file for write
            OpenBinFileForWrite(std::move(File), NameFile);
            File->write((char*) &Quantity, sizeof(uint32));//РАБОТАЕТ!!!
}



А так НЕ работает:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
void OpenBinFileForWrite(std::unique_ptr<std::ofstream> File, cstring& FileName);
void WriteArrayToBinFile(const VariativeData& Settings, cstring& NameFile) const
{
             auto File = std::make_unique<std::ofstream>;

            //open file for write
            OpenBinFileForWrite(std::move(File), NameFile);
            File->write((char*) &Quantity, sizeof(uint32));//ОШИБКА!!! File = (null)
}



Другими словами, правые ссылки позволяет передать временное значение без вызовов конструктора перемещения и/ или перемещающего оператора присваивания. А значит исходная переменная не зануляется. Вот зачем они нужны!!! Этого вы нигде не прочитаете.
...
Рейтинг: 0 / 0
01.05.2018, 11:39
    #39638652
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
move- семантика: как передать unique_ptr?
AlekseySQLДругими словами, правые ссылки позволяет передать временное значение без вызовов конструктора перемещения и/ или перемещающего оператора присваивания. А значит исходная переменная не зануляется .
Значение не зануляется самим фактом передачи ссылки.
Но если вы передали rv-ссылку в функцию, то вы уже не можете рассчитывать что значение сохранится. Хотя конечно никто не обязывает функцию что либо делать с переданным значением.
...
Рейтинг: 0 / 0
01.05.2018, 18:32
    #39638786
AlekseySQL
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
move- семантика: как передать unique_ptr?
Anatoly MoskovskyЗначение не зануляется самим фактом передачи ссылки.
Но если вы передали rv-ссылку в функцию, то вы уже не можете рассчитывать что значение сохранится. Хотя конечно никто не обязывает функцию что либо делать с переданным значением.

В том- то и фишка:
1. Если принимаем по значению, то будет вызван оператор перемещающего копирования, который как правило переданный в него параметр зануляет (освобождает ресурсы). Т.е. зануление происходит ВСЕГДА.
2. Если мы принимаем по правой ссылке, то это по смыслу тоже самое, как передать обычный указатель или обычную ссылку (которые сами передаются по значению). При этом передается адрес, а не сама переменная, поэтому никаких конструкторов не вызывается и потому переданная переменная не теряет значение из-за действий конструктора. Т.е. зануление происходит, если в принимающей функции (или передавая ниже по стеку) мы явно вызовем перемещения.

Для некопируемых (но перемещаемых) объектов это очень важно: их нужно отдавать в функции как правые ссылки (с помощью std::move), принимать как правые ссылки (с помощью &&), но в принимающей функции ни в коем случае не перемещать: потому что по сути мы работаем с исходной переменной и ее перемещение занулит исходную переменную.
...
Рейтинг: 0 / 0
01.05.2018, 18:44
    #39638790
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
move- семантика: как передать unique_ptr?
AlekseySQL,

&& и & ссылки ничем не отличаются на принимающей стороне.
Разница только в том, что туда можно передать.
...
Рейтинг: 0 / 0
02.05.2018, 08:21
    #39638876
AlekseySQL
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
move- семантика: как передать unique_ptr?
Anatoly MoskovskyAlekseySQL,

&& и & ссылки ничем не отличаются на принимающей стороне.
Разница только в том, что туда можно передать.

Ок.
...
Рейтинг: 0 / 0
02.05.2018, 08:40
    #39638878
AlekseySQL
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
move- семантика: как передать unique_ptr?
Anatoly MoskovskyAlekseySQL,

&& и & ссылки ничем не отличаются на принимающей стороне.
Разница только в том, что туда можно передать.

Если принимать по константной ссылке (как левой, так и правой), то программа тоже работает без ошибок.

Какую ссылку лучше выбрать, если принимающая сторона работает с константным объектом? По логике лучше прямо это показать, использую левую ссылку: правые для изменений, левые для константных объектов. Я прав?
...
Рейтинг: 0 / 0
02.05.2018, 15:07
    #39639006
AlekseySQL
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
move- семантика: как передать unique_ptr?
Anatoly MoskovskyAlekseySQL,

&& и & ссылки ничем не отличаются на принимающей стороне.
Разница только в том, что туда можно передать.

Если принимать по константной ссылке (как левой, так и правой), то программа тоже работает без ошибок.

Какую ссылку лучше выбрать, если принимающая сторона работает с константным объектом? По логике лучше прямо это показать, использую левую ссылку: правые для изменений, левые для константных объектов. Я прав?
...
Рейтинг: 0 / 0
03.05.2018, 05:35
    #39639137
CEMb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
move- семантика: как передать unique_ptr?
NekZВ этом недостаток auto, так что будь внимателен, когда используешь его.не надо использовать auto где попало. Он сделан не для того, чтобы сокращать длинные декларации. Для этого есть using, надо использовать его. Уже не первый раз тут(и не тут) пишут про ошибки, которые возникли из-за того, что автор использовал auto, чтобы "упростить" код.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / move- семантика: как передать unique_ptr? / 13 сообщений из 13, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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