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

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

06.09.2015, 19:58. Показов 2632. Ответов 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
Ответ Создать тему
Новые блоги и статьи
сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и источниками (напряжения, ЭДС и тока). Найти токи и напряжения во всех элементах. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru