Эксперт .NET
4428 / 2088 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
1

Почему не вызывается конструктор перемещения? И есть ли ошибки в коде?

16.12.2018, 22:58. Показов 655. Ответов 5
Метки нет (Все метки)

Если вы увидели здесь что-то, что на приличной работе бы не пропустили по ревью, так как там С стиль, то напишите об этом. Мне интересно, что не стоит в принципе использовать. Но этот пример просто учебный. В целях понимания и пишутся все эти массивы странные и т.д.

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
#pragma once
#include <string>
 
namespace ClassesAndStructs
{
    class Person
    {
    public:
        Person(const Person& person);         // Конструктор копирования
        Person(Person&& person) noexcept;     // Конструктор перемещения
        Person(const std::string& firstName, const std::string& lastName);
        ~Person();
        void SetFirstName(const std::string& firstName);
        std::string GetFullName() const;
        const int32_t* GetData() const;
 
        const int32_t DATA_SIZE = 50;
    private:
        std::string _firstName;
        std::string _lastName;
 
        int32_t * _data;
    };
}
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
#include "Person.h"
 
namespace ClassesAndStructs
{
    Person::Person(const std::string& firstName, const std::string& lastName)
    {
        _firstName = firstName;
        _lastName = lastName;
 
        _data = new int32_t[DATA_SIZE];
        for (int32_t i = 0; i < DATA_SIZE; ++i)
        {
            *(_data + i) = i; // Просто для примера - арифметика указателей
        }
    }
 
    Person::Person(const Person& person) // Конструктор копирования
        : _data(nullptr)
    {
        _firstName = person._firstName;
        _lastName = person._lastName;
 
        int32_t* newData = new int32_t[DATA_SIZE];
        std::copy(person._data, person._data + DATA_SIZE, newData);
        _data = newData;
    }
 
    Person::Person(Person&& person) noexcept // Конструктор перемещения
    {
        _firstName = std::move(person._firstName);
        _lastName = std::move(person._lastName);
 
        _data = person._data;
    }
 
    Person::~Person()
    {
        delete[] _data;
        _data = nullptr;
    }
 
    void Person::SetFirstName(const std::string& firstName)
    {
        _firstName = firstName;
    }
 
    std::string Person::GetFullName() const
    {
        return _firstName + " " + _lastName;
    }
 
    const int32_t* Person::GetData() const
    {
        return _data;
    }
}
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
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <string>
#include "Person.h"
#include <iomanip>
 
using namespace ClassesAndStructs;
 
void pause(const std::string &text);
Person copyPerson(Person& person);
Person modifyPerson(Person& person);
void display(const std::string& message, Person& person);
void display(int const *array, int arraySize);
 
int main()
{
    using namespace  std;
    cin.putback('\n');
 
    Person person1("John", "Smith");
    display("Before copying", person1);
 
    Person person2 = copyPerson(person1);
    display("After copying", person2);
 
    Person person3 = modifyPerson(person1);
    display("After modifying", person3);
    
    pause("Pause");
    return 0;
}
 
void display(const std::string& message, Person& person)
{
    std::cout << message << " " << person.GetFullName() << std::endl;
    display(person.GetData(), person.DATA_SIZE);
}
 
void display(int const *array, int arraySize)
{
    using namespace  std;
 
    cout << ": {";
    for (int i = 0; i < arraySize; ++i)
    {
        cout << setw(3) << *(array + i) << ",";
    }
    cout << '\b' << " }" << endl;
}
 
void pause(const std::string &text = "")
{
    using namespace  std;
 
    if (text.length() > 0) { cout << text << endl; }
    if (cin.fail()) { cin.clear(); }
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    cin.get();
}
 
Person copyPerson(Person& person)
{
    return Person(person);
}
 
Person modifyPerson(Person& person)
{
    person.SetFirstName("modifyPerson");
    return person;
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
16.12.2018, 22:58
Ответы с готовыми решениями:

Почему не вызывается конструктор перемещения?
#include &lt;iostream&gt; #include &lt;vector&gt; class Object { public: Object() { std::cout &lt;&lt;...

Почему не вызывается конструктор копии?
Почему не вызывается конструктор копии? class CPoint { friend std::istream...

Почему не вызывается конструктор копирования?
...У меня в книге описаны случаи при которых вызывается конструктор копирования. Один из этих...

Почему вызывается конструктор копий по умолчанию?
Всем добрый день! Не могу понять, почему не вызывается конструктор копий. Вот, для примера, код: ...

5
112 / 91 / 31
Регистрация: 24.10.2018
Сообщений: 336
16.12.2018, 23:10 2
Цитата Сообщение от Casper-SC Посмотреть сообщение
Почему не вызывается конструктор перемещения?
Где ты ожидаешь его вызов?
0
Эксперт .NET
4428 / 2088 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
16.12.2018, 23:17  [ТС] 3
modifyPerson модифицирует person1 и вызвав конструктор копирования копирует. Так что название функции чуть не в тему. Я надеялся, что там будет при возврате вызван конструктор перемещения, но увы.

Добавлено через 28 секунд
Цитата Сообщение от krolligator Посмотреть сообщение
Где ты ожидаешь его вызов?
При возврате из copyPerson и modifyPerson

Добавлено через 38 секунд
В книге написано, что если создать конструктор перемещения, то компилятор будет использовать его, а не конструктор копирования при возврате из функции. Или я, возможно, чего-то не понял в книге.

Добавлено через 2 минуты
В качестве DATA_SIZE, похоже, нужно использовать size_t?

Добавлено через 1 минуту
И здесь тоже нужно использовать size_t вместо int32_t?
C++
1
for (int32_t i = 0; i < DATA_SIZE; ++i)
0
112 / 91 / 31
Регистрация: 24.10.2018
Сообщений: 336
16.12.2018, 23:38 4
Цитата Сообщение от Casper-SC Посмотреть сообщение
При возврате из copyPerson
Зачем лишний раз вызывать конструктор перемещения, если уже все на местах? person не временный объект. Объект конструируется из person1 на месте в памяти. По сути, это просто Person person2{person1};. Больше никаких лишних конструкторов не нужно.
Цитата Сообщение от Casper-SC Посмотреть сообщение
и modifyPerson
Здесь вообще нельзя, этот объект пришел извне. Почему он вдруг должен стать rvalue?
0
Эксперт .NET
4428 / 2088 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
17.12.2018, 00:04  [ТС] 5
Цитата Сообщение от krolligator Посмотреть сообщение
Здесь вообще нельзя, этот объект пришел извне. Почему он вдруг должен стать rvalue?
Да, точно. Я пока не всё идеально уловил, нужно время и практика.

Добавлено через 2 минуты
Цитата Сообщение от krolligator Посмотреть сообщение
Зачем лишний раз вызывать конструктор перемещения, если уже все на местах? person не временный объект.
C++
1
2
3
4
Person copyPerson(Person& person)
{
    return Person(person);
}
Передали в функцию copyPerson по ссылке объект person, создали на стеке новый объект типа Person, в копирующий конструктор которого по ссылке был передан исходный объект person. Далее идёт возврат созданного на стеке в области видимости функции copyPerson объекта типа Person, вот во время его возврата из функции я ожидаю не вызов конструктора копирования (что происходит по факту), а вызов конструктора перемещения ибо глубинное копирование здесь излишне.
0
112 / 91 / 31
Регистрация: 24.10.2018
Сообщений: 336
17.12.2018, 00:14 6
Цитата Сообщение от Casper-SC Посмотреть сообщение
В качестве DATA_SIZE, похоже, нужно использовать size_t?
Можно.

Добавлено через 7 минут
Цитата Сообщение от Casper-SC Посмотреть сообщение
вот во время его возврата из функции я ожидаю не вызов конструктора копирования (что происходит по факту)
А он вызывает не во время возврата, а во время Person(person); person это не rvalue. Он обязан вызвать конструктор копирования здесь. А уже при возврате может вызвать констркутор перемещения. А может оптимизировать код так, что он, по сути, превратится, грубо, в Person person2{person1}; без вызова констркутора перемещения.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
17.12.2018, 00:14
Помогаю со студенческими работами здесь

Почему вызывается конструктор, а не создание массива?
struct KTest { KTest(int _a, double _b, long long _c) : a(_a), b(_b), c(_c) {} friend ostream&amp;...

Почему Конструктор не вызывается и не присваивает введенные значения?
Ребят, подскажите пожалуйста, почему значение в скобках не присвоились(выдает 0)? Путаюсь с...

Почему нельзя так делать? Конструктор перемещения?
У меня возникла проблема с хранением объектов класса в векторе векторов, объявленном в другом...

Почему конструктор вызывается повторно при преобразовании типов?
В качестве примера предлагаю рассмотреть примерчик из учебника. В примере мы создаём класс,...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru