Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.85/13: Рейтинг темы: голосов - 13, средняя оценка - 4.85
 Аватар для gromo
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225

Не срабатывает move конструктор std::unique_ptr

06.09.2015, 19:58. Показов 2688. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет! Битый час не пойму почему в списке захвата компилятор ругается на удаленный копирующий конструктор unique_ptr, если я его перемещаю.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <memory>
#include <iostream>
class A {
 
    void member()
    {
        auto p = std::make_unique<int>(42);
        const std::vector<int> f {1, 3, 4};
        if(std::find_if(f.cbegin(), f.cend(),
             [ p { std::move(p) } ](int val) {  return val == 5 ? true : false ;}) == f.cend() )
             std::cout << "Not found" << std::endl;
 
    }
};
int main(){}
Ошибки:
Кликните здесь для просмотра всего текста
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
In file included from /usr/include/c++/5.2.0/algorithm:62:0,
                 from ../../qt_projects/expert/main.cpp:227:
/usr/include/c++/5.2.0/bits/stl_algo.h: In instantiation of '_IIter std::find_if(_IIter, _IIter, _Predicate) [with _IIter = __gnu_cxx::__normal_iterator<const int*, std::vector<int> >; _Predicate = A::member()::<lambda(int)>]':
../../qt_projects/expert/main.cpp:259:122:   required from here
/usr/include/c++/5.2.0/bits/stl_algo.h:3816:37: error: use of deleted function 'A::member()::<lambda(int)>::<lambda>(const A::member()::<lambda(int)>&)'
        __gnu_cxx::__ops::__pred_iter(__pred));
                                     ^
../../qt_projects/expert/main.cpp:259:75: note: 'A::member()::<lambda(int)>::<lambda>(const A::member()::<lambda(int)>&)' is implicitly deleted because the default definition would be ill-formed:
         auto iter = std::find_if(f.cbegin(), f.cend(), [p { std::move(p) }](int val) {  return val == 5 ? true : false ;});
                                                                           ^
../../qt_projects/expert/main.cpp:259:75: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]'
In file included from /usr/include/c++/5.2.0/memory:81:0,
                 from ../../qt_projects/expert/main.cpp:251:
/usr/include/c++/5.2.0/bits/unique_ptr.h:356:7: note: declared here
       unique_ptr(const unique_ptr&) = delete;
       ^
In file included from /usr/include/c++/5.2.0/bits/stl_algobase.h:71:0,
                 from /usr/include/c++/5.2.0/vector:60,
                 from ../../qt_projects/expert/main.cpp:225:
/usr/include/c++/5.2.0/bits/predefined_ops.h:239:5: note:   initializing argument 1 of '__gnu_cxx::__ops::_Iter_pred<_Predicate> __gnu_cxx::__ops::__pred_iter(_Predicate) [with _Predicate = A::member()::<lambda(int)>]'
     __pred_iter(_Predicate __pred)
     ^
/usr/include/c++/5.2.0/bits/predefined_ops.h: At global scope:
/usr/include/c++/5.2.0/bits/predefined_ops.h:239:5: error: '__gnu_cxx::__ops::_Iter_pred<_Predicate> __gnu_cxx::__ops::__pred_iter(_Predicate) [with _Predicate = A::member()::<lambda(int)>]', declared using local type 'A::member()::<lambda(int)>', is used but never defined [-fpermissive]

Переместить лямбду тоже не получается, ибо, как я понимаю, перемещение unique_ptr inside lambda-capture list делает функтор non-copyable.
Типа такого:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
class A {
 
 
    void member()
    {
        auto p = std::make_unique<int>(42);
        const std::vector<int> f {1, 3, 4};
 
        auto lam = [ p { std::move(p) } ](int val) {  return val == 5 ? true : false ;};
        auto iter = std::find_if(f.cbegin(), f.cend(), std::move(lam));
 
    }
};
Что за дела?
Спасибо!
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
06.09.2015, 19:58
Ответы с готовыми решениями:

Использование std::unique_ptr
Есть в коде подобная конструкция, вылетает исключение на этапе очистки памяти. С чем это может быть связано? template &lt;typename T&gt;...

Компилятор не видит std::unique_ptr
Не создается unique_ptr int main(int argc, char *argv) { QCoreApplication a(argc, argv); ...

Отсутствует std::unique_ptr gcc 4.8.1
всем привет , я в С++ начинающий и возникла проблема не работает std::unique_ptr версия компилятора gcc 4.8.1(tdm 2) флаг...

13
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
06.09.2015, 20:05
Цитата Сообщение от gromo Посмотреть сообщение
Всем привет! Битый час не пойму почему в списке захвата компилятор ругается на удаленный копирующий конструктор unique_ptr, если я его перемещаю.
ваш код:
http://rextester.com/TOW5373

как видите все компилируется, и работает.

единственное:
я поставил ключик -std=c++1y
что бы активировать с++14
1
 Аватар для gromo
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
06.09.2015, 20:10  [ТС]
Цитата Сообщение от hoggy Посмотреть сообщение
как видите все компилируется, и работает.
Да что ж это такое, целый день сегодня сижу над ним, выдает одну и ту же ошибку, а в онлайн-компиляторе работает.
Цитата Сообщение от hoggy Посмотреть сообщение
единственное:
я поставил ключик -std=c++1y
что бы активировать с++14
У меня вообще опции всегда -std=c++1z -Wpedantic -Wextra
Code
1
2
3
4
5
$ g++ --version
g++ (GCC) 5.2.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Проект пересобирал уже, естественно...
0
2444 / 1842 / 406
Регистрация: 15.12.2013
Сообщений: 8,243
06.09.2015, 20:17
Цитата Сообщение от gromo Посмотреть сообщение
а в онлайн-компиляторе работает.
не во всех:
http://ideone.com/6L2tlC
0
 Аватар для gromo
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
06.09.2015, 20:19  [ТС]
Цитата Сообщение от S_el Посмотреть сообщение
не во всех:
Я вообще в непонятках полностью… Раньше вроде бы всегда работало, а теперь перестало.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
06.09.2015, 20:21
Лучший ответ Сообщение было отмечено gromo как решение

Решение

Цитата Сообщение от gromo Посмотреть сообщение
Я вообще в непонятках полностью… Раньше вроде бы всегда работало, а теперь перестало.
на референсах пишут:

The behavior of this function template is equivalent to:
C++
1
2
3
4
5
6
7
8
9
template<class InputIterator, class UnaryPredicate>
  InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred)
{
  while (first!=last) {
    if (pred(*first)) return first;
    ++first;
  }
  return last;
}

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

может быть в этом все дело?

http://ideone.com/PiDdDk
1
2444 / 1842 / 406
Регистрация: 15.12.2013
Сообщений: 8,243
06.09.2015, 20:22
gromo, Меня эта конструкция тоже удивляет Почему не сделаете доступ по ссылке?
0
 Аватар для gromo
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
06.09.2015, 20:34  [ТС]
Цитата Сообщение от hoggy Посмотреть сообщение
обратите внимание: предикат принимается по значению, а не по ссылке.
то есть копируется.
то есть лямбда должна уметь копироваться.
может быть в этом все дело?
Была такая мысль, но я думал что на референсе это чисто схематическая реализация и там на самом деле все как надо, через universal references.
Походу дело действительно в этом.
C++
1
2
3
4
5
6
7
8
9
10
11
12
template <class P> void f(P pred)
{
    pred();
 
}
 
int main()
{
    auto p = std::make_unique<int>(42);
    auto lam = [p { std::move(p) } ]() {  std::cout << "HEllo\n"; };
    f(/*std::move(*/lam/*)*/);     // OK if uncomment.
}
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
../../qt_projects/expert/main.cpp: In function 'int main()':
../../qt_projects/expert/main.cpp:280:29: error: use of deleted function 'main()::<lambda()>::<lambda>(const main()::<lambda()>&)'
     f(/*std::move(*/lam/*)*/);
                             ^
../../qt_projects/expert/main.cpp:279:36: note: 'main()::<lambda()>::<lambda>(const main()::<lambda()>&)' is implicitly deleted because the default definition would be ill-formed:
     auto lam = [p { std::move(p) } ]() {  std::cout << "HEllo\n"; };
                                    ^
../../qt_projects/expert/main.cpp:279:36: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]'
In file included from /usr/include/c++/5.2.0/memory:81:0,
                 from ../../qt_projects/expert/main.cpp:251:
/usr/include/c++/5.2.0/bits/unique_ptr.h:356:7: note: declared here
       unique_ptr(const unique_ptr&) = delete;
       ^
../../qt_projects/expert/main.cpp:268:25: note:   initializing argument 1 of 'void f(P) [with P = main()::<lambda()>]'
 template <class P> void f(P pred)
                         ^
Добавлено через 5 минут
Цитата Сообщение от S_el Посмотреть сообщение
Почему не сделаете доступ по ссылке?
Так и сделаю Просто хотел более идиоматически поступить, но как видите — писатели std::find_if не позаботитились о таком юзкейсе.

Всего-то дописать && после типа предиката…
0
2444 / 1842 / 406
Регистрация: 15.12.2013
Сообщений: 8,243
06.09.2015, 20:51
Цитата Сообщение от gromo Посмотреть сообщение
Просто хотел более идиоматически поступить
А что тут более идиоматичного?

Цитата Сообщение от hoggy Посмотреть сообщение
может быть в этом все дело?
Да. Посмотрел у Джосаттиса,пишет,что стандарт не регламентирует количество копирований предиката.

Добавлено через 4 минуты
gromo, кстати, поведение будет отличатся в зависимости от передачи. После такой лямбды
C++
1
[ p { std::move(p) } ]
указатель p станет пустым.
0
 Аватар для gromo
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
06.09.2015, 20:52  [ТС]
Цитата Сообщение от S_el Посмотреть сообщение
А что тут более идиоматичного?
Ну во-первых, новая возможность С++14. Во-вторых, а что если будет такая ситуация, что контекст, содержащий unique_ptr перестанет существовать, когда лямбда будет еще жива и выполняться? В моем случае это невозможно, поэтому захват по ссылке сослужил полезную службу.
Цитата Сообщение от S_el Посмотреть сообщение
Да. Посмотрел у Джосаттиса,пишет,что стандарт не регламентирует количество копирований предиката.
Тут дело не в количестве копирований. В данном случае даже одно, самое первое копирование произойти не может ибо ClosureType содержит в себе перемещенный unique_ptr, который, использую автоматически сгенерированный defaulted копирующий конструктор скопировать не получится. Вылазит ошибка выше.

Добавлено через 59 секунд
Цитата Сообщение от S_el Посмотреть сообщение
указатель p станет пустым.
ну это конечно, ведь он больше мне не нужен в своем старом контексте, поэтому я его хотел переместить с глаз долой.
1
2444 / 1842 / 406
Регистрация: 15.12.2013
Сообщений: 8,243
06.09.2015, 20:56
Цитата Сообщение от gromo Посмотреть сообщение
ну это конечно, ведь он больше мне не нужен в своем старом контексте, поэтому я его хотел переместить с глаз долой.
Тогда не забудьте обнулить после передачи по ссылке.

Цитата Сообщение от gromo Посмотреть сообщение
Тут дело не в количестве копирований.
Я понимаю

Цитата Сообщение от gromo Посмотреть сообщение
Во-вторых, а что если будет такая ситуация, что контекст, содержащий unique_ptr перестанет существовать, когда лямбда будет еще жива и выполняться?
Да,я не подумал о такой возможности.
0
 Аватар для gromo
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
06.09.2015, 21:00  [ТС]
Цитата Сообщение от S_el Посмотреть сообщение
Тогда не забудьте обнулить после передачи по ссылке.
Зачем? Может вы имели ввиду "после перемещения"?
0
2444 / 1842 / 406
Регистрация: 15.12.2013
Сообщений: 8,243
06.09.2015, 21:11
Цитата Сообщение от gromo Посмотреть сообщение
Зачем? Может вы имели ввиду "после перемещения"?
Нет. После перемещения он сам станет пустым,но если вы сделаете передачу в лямбду по ссылке,то никакого перемещения не будет и его надо будет "уничтожить".
Т.е. в таком случае вы не сможете добиться поведения - лямбда живет независимо от указателя.
0
 Аватар для gromo
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
06.09.2015, 21:26  [ТС]
S_el, RAII?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
06.09.2015, 21:26
Помогаю со студенческими работами здесь

Копирование объектов std::unique_ptr
привет, столкнулся с такой ситуацией, что вроде как копировать объекты std::unique_ptr запрещено, но тем не менее такой код...

Std::unique_ptr virtual метод
#include &lt;iostream&gt; #include &lt;memory&gt; class Base { public: virtual void f1(); // Virtual function. }; class Derived...

Копирование std::unique_ptr в структуре
Есть структуры и vector struct myStruct { int a; int b; void* param; }; struct sSetup { int x; int y;

Проблема с умным указателем std::unique_ptr
здравствуйте. есть задание - написать небольшую простенькую игру, где есть базовый класс Unit, кроме него есть ещё три класса -...

Шаблонные аргументы конструктора std::unique_ptr
Если я пишу код std::unique_ptr&lt;int, void(*)(int*)&gt; myPtr_5(new int, (int* p) {delete p; }); то все приятно, и компилируется без...


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&amp;d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru