Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
GbaLog-
Любитель чаепитий
3092 / 1431 / 346
Регистрация: 24.08.2014
Сообщений: 5,077
Записей в блоге: 1
Завершенные тесты: 2
#1

Optional и std::move - C++

11.05.2017, 12:50. Просмотров 380. Ответов 15
Метки нет (Все метки)

добрый день.
разбираясь в исходниках optional'а из gcc, я понял, что там нигде не делается инвалидным только что перемещенный объект.
то есть вот такой код:
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
37
38
39
40
41
#include <iostream>
#include <experimental/optional>
 
namespace stdEx = std::experimental;
 
struct A
{
    A(int) { std::cout << "ctor\n"; }
    A(const A&) { std::cout << "copy ctor\n"; }
    A(A&&) { std::cout << "move ctor\n"; }
    A & operator =(const A&) { std::cout << "operator =\n"; return *this; }
    ~A() { std::cout << "dtor\n"; }
};
 
int main()
{
    stdEx::optional<A> o1(123);
    stdEx::optional<A> o2;
    
    std::cout << "checkpoint 1\n";
    
    std::cout << std::boolalpha;
    
    std::cout
        << static_cast<bool>(o1)
        << " "
        << static_cast<bool>(o2)
        << "\n";
    
    o2 = std::move(o1);
    
    std::cout << "checkpoint 2\n";
    
    std::cout 
        << static_cast<bool>(o1)
        << " "
        << static_cast<bool>(o2)
        << "\n";
    
    std::cout << "checkpoint 3\n";
}
выводит:
Код
ctor
move ctor
dtor
checkpoint 1
true false
move ctor
checkpoint 2
true true
checkpoint 3
dtor
dtor
на gcc и clang'e.
я, возможно, не до конца логику перемещения понимаю, но разве между checkpoint 2 и checkpoint 3 не должно стоять false true?
эту тему прочитал и не понял, почему работает не так, как я ожидаю.
Собеседование std::vector
то есть std::vector вполне может после перемещения из метода empty() вернуть false?
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.05.2017, 12:50
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Optional и std::move (C++):

Std::move - C++
Добрый вечер, #include &lt;iostream&gt; using namespace std; class A { private: int x = 10; public: A(int q){ x = q; }

std::move() - C++
Есть ли разница между следующими вещами: A = std::move(B); // and std::copy(B.begin(), B.end(), A.begin()); B.clear();

Немного не понимаю std::move - C++
Здравствуйте, я немного не понимаю работу кода на 150-155 строках здесь: #include &lt;iostream&gt; #include &lt;memory&gt; #include...

std::move, rvalue reference - C++
Здравствуйте! Недавно начал разбираться с новыми способами передачи аргументов. Прочитал около 10 статей, некоторые на русском, некоторые...

Func(std::move(.) копирует ? - C++
Здравствуйте, имеется следующий код: void foo(std::vector&lt;int&gt;&amp;&amp; v) { std::cout &lt;&lt; &quot;vector is taken&quot; &lt;&lt; std::endl; ...

Std::move stl-алгоритм - C++
здравствуйте, есть такой код: std::string his = &quot;what the work ?&quot;; std::istringstream isg(his); ...

15
MrGluck
Модератор
Эксперт CЭксперт С++
7521 / 4659 / 703
Регистрация: 29.11.2010
Сообщений: 12,715
11.05.2017, 13:13 #2
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Типичное состояние unspecified state.
Objects of types defined in the C++ standard library may be moved from (12.8). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.
То есть полагаться на данные объекта бессмысленно, компилятор может затереть их сразу/затереть их потом/не затирать их вообще/делать это по настроению. Хозяин-барин
1
GbaLog-
Любитель чаепитий
3092 / 1431 / 346
Регистрация: 24.08.2014
Сообщений: 5,077
Записей в блоге: 1
Завершенные тесты: 2
11.05.2017, 13:22  [ТС] #3
Цитата Сообщение от MrGluck Посмотреть сообщение
То есть полагаться на данные объекта бессмысленно
но как же быть, если у меня дальше по коду будет, например, if (o1) { ... } ?
по идее предусловие соблюдено, но результат будет неверным.
как поступить?
0
DU3
281 / 233 / 80
Регистрация: 07.09.2016
Сообщений: 587
11.05.2017, 13:28 #4
C++
1
 o2 = o1; // так, не?
с какой целью вы сделали именно std::move, а не просто копию
0
Max Dark
шКодер самоучка
1854 / 1654 / 603
Регистрация: 09.10.2013
Сообщений: 3,679
Записей в блоге: 6
Завершенные тесты: 2
11.05.2017, 13:29 #5
Цитата Сообщение от GbaLog- Посмотреть сообщение
но как же быть, если у меня дальше по коду будет, например
перемещение (как я понимаю) подразумевает передачу владения ресурсами и дальнейшее использование перемещаемого объекта невозможно.
0
GbaLog-
Любитель чаепитий
3092 / 1431 / 346
Регистрация: 24.08.2014
Сообщений: 5,077
Записей в блоге: 1
Завершенные тесты: 2
11.05.2017, 13:43  [ТС] #6
Цитата Сообщение от Max Dark Посмотреть сообщение
дальнейшее использование перемещаемого объекта невозможно.
да с чего бы?
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>
#include <vector>
 
struct IParserUser
{
    virtual ~IParserUser() {}
    virtual void onData(std::vector<int> &&) = 0;
};
 
struct ParserUser : public IParserUser
{
    virtual void onData(std::vector<int> && data) override
    {
        std::cout << "onData called\n";
        for (const auto & it : data)
            std::cout << it << ' ';
        std::cout << "\n";
    }
};
 
struct Parser
{
    Parser(IParserUser & user) :
        buffer_{},
        user_{user}
    {}
    
    void parse(int val)
    {
        buffer_.push_back(val);
        
        if (buffer_.size() == 3)
        {
            user_.onData(std::move(buffer_));
            buffer_.clear();
        }
    }
    
    template<typename ... Args>
    void parse(Args &&... args)
    {
        using dummy = char[];
        
        (void)dummy{ (parse(std::forward<Args>(args)), static_cast<char>(0))... };
    }
 
private:
    std::vector<int> buffer_;
    IParserUser & user_;
};
 
int main()
{
    ParserUser user;
    
    Parser parser(user);
    
    parser.parse(1, 2, 3, 4, 5, 6, 7);
}
Добавлено через 4 минуты
внезапно для себя обнаружил reset у optional'a.
0
DU3
281 / 233 / 80
Регистрация: 07.09.2016
Сообщений: 587
11.05.2017, 13:48 #7
Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state
как это можно трактовать: если в вашем случае специально для вектора оговорено, что будет валидное состояние после мува, да еще и вектор почистится - ок. возможно так можно делать. а если не оговорено, то в одной реализации может
быть одно, в другой - другое. в том числе и невалидное состояние. например буфера подчистятся, а переменная,
которая за размер отвечает - не обнулится. и получится такой пустой не пустой вектор, обращения к элементам которого
чреваты UB. Помимо вектора есть еще тьма других типов и что для них в стандарте прописано - хз. В общем так наверно лучше не делать.
0
MrGluck
Модератор
Эксперт CЭксперт С++
7521 / 4659 / 703
Регистрация: 29.11.2010
Сообщений: 12,715
11.05.2017, 13:53 #8
Цитата Сообщение от Max Dark Посмотреть сообщение
дальнейшее использование перемещаемого объекта невозможно.
Небольшая поправочка. Возможно, но полагаться на данные уже нельзя. Например, после перемещения std::vector, можно вызвать метод .clear() и потом снова работать с объектом.
1
GbaLog-
Любитель чаепитий
3092 / 1431 / 346
Регистрация: 24.08.2014
Сообщений: 5,077
Записей в блоге: 1
Завершенные тесты: 2
11.05.2017, 13:58  [ТС] #9
я понял, в std::optional в gcc и clang не завезли метод reset.
поэтому я его не видел.
0
Undisputed
172 / 103 / 21
Регистрация: 10.06.2014
Сообщений: 1,428
Завершенные тесты: 3
11.05.2017, 15:40 #10
Насколько я помню при перемещении обнуляются все указатели в перемещаемом объекте, но перед этим их адрес присваивается приемнику. Все что не является указателем, по идее тупо должно копироваться...

Поправьте если ошибаюсь
0
Max Dark
шКодер самоучка
1854 / 1654 / 603
Регистрация: 09.10.2013
Сообщений: 3,679
Записей в блоге: 6
Завершенные тесты: 2
11.05.2017, 15:55 #11
Undisputed, необязательно - сам std::move ничего не делает, только помечает объект как готовый к перемещению(преобразует к rvalue reference).
Остальное зависит от принимающей стороны.
0
Undisputed
172 / 103 / 21
Регистрация: 10.06.2014
Сообщений: 1,428
Завершенные тесты: 3
11.05.2017, 15:57 #12
Max Dark,
Ну я говорил про саму реализацию конструктора перемещения по умолчанию а мув это да, там просто каст
0
MrGluck
Модератор
Эксперт CЭксперт С++
7521 / 4659 / 703
Регистрация: 29.11.2010
Сообщений: 12,715
11.05.2017, 15:59 #13
Парадокс С++ функция move ничего не перемещает
0
Ferrari F1
622 / 519 / 101
Регистрация: 27.01.2015
Сообщений: 3,025
Записей в блоге: 1
Завершенные тесты: 1
11.05.2017, 16:01 #14
Цитата Сообщение от MrGluck Посмотреть сообщение
ничего не перемещает
смотря о какой функции говорить
0
Max Dark
шКодер самоучка
1854 / 1654 / 603
Регистрация: 09.10.2013
Сообщений: 3,679
Записей в блоге: 6
Завершенные тесты: 2
11.05.2017, 16:26 #15
Цитата Сообщение от Undisputed Посмотреть сообщение
Ну я говорил про саму реализацию конструктора перемещения по умолчанию
Надо будет уточнить этот момент...
Но мне кажется, что он равносилен вызову конструктора перемещения для всех полей класса, а для фундаментальных типов будет выполнено простое копирование.
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
// ideone.com/feD35C
#include <iostream>
#include <string>
using namespace std;
 
struct ctor
{
    ctor()            { std::cout << __PRETTY_FUNCTION__ << std::endl; }
    ctor(const ctor&) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
    ctor(ctor&&)      { std::cout << __PRETTY_FUNCTION__ << std::endl; }
    ~ctor()           { std::cout << __PRETTY_FUNCTION__ << std::endl; }
 
    void* ptr = (void*)0xdead;
};
 
struct test
{
    ctor obj;
};
 
int main() {
    test t1;
    
    test t2{std::move(t1)};
    
    std::cout << "t2 " << t2.obj.ptr << std::endl;
    std::cout << "t1 " << t1.obj.ptr << std::endl;
    
    return 0;
}
1
11.05.2017, 16:26
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.05.2017, 16:26
Привет! Вот еще темы с ответами:

Error: 'move' is not a member of 'std' - C++
Как бороться с этой гогой?

Не срабатывает move конструктор std::unique_ptr - C++
Всем привет! Битый час не пойму почему в списке захвата компилятор ругается на удаленный копирующий конструктор unique_ptr, если я его...

Vector::swap и std::move - что эффективнее? - C++
Пусть имеется пустой вектор A и заполненный некими данными вектор B. Тогда какой из методов более эффективный: A.swap(B); A =...

Что происходит когда std::move применяется для int? - C++
Мне, вроде бы, понятно как работает std::move() на классах типа string. Но мне непонятно что будет в данном случаи. #include &lt;iostream&gt; ...


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

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

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