Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/9: Рейтинг темы: голосов - 9, средняя оценка - 5.00
 Аватар для Lagos
11 / 11 / 6
Регистрация: 19.01.2012
Сообщений: 195
Записей в блоге: 2

Грамотное использование конструктора копирования

19.12.2016, 01:54. Показов 1893. Ответов 9
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем добрый вечер. Есть класс list(двухсвязный). Задача гласит: Сгенерировать некоторую последовательность чисел, вывести на экран, и затем "исправить" последовательность, записав сначала четные, а затем нечетные элементы массива в нее.
Все реализовано, но проблема в том, что в функции-члене класса создается и возвращается новый объект, с использованием конструктора копирования. Но, данные не переносятся в новый объект. Прошу помочь разобраться, где ошибка в сосздании контсруктора копирования. Вот код:
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
class ListD
{
private:
    ListD* head;
    ListD* end;
    ListD* next;
    ListD* prew;
    int number;
public:
    ListD(const ListD &l) // конструктор копирования
    {
        ListD *tmp = new ListD;
        ListD* temp = l.head;
        while (temp)
        {
            tmp->add(&temp->number);
            temp = temp->next;
        }
        wcout << L"Сработал конструктор копирования.\n";
    }
    ListD()
    {
        head = end = NULL;
    }
    void add(int*);
    void show();
    ListD replacementEvenOddNoMassiv(); // метод
    ~ListD()
    {
        ListD *tmp(head);
        while (head)
        {
            tmp = tmp->next;
            delete head;
            head = tmp;
        }
    }
};
 
void ListD::add(int* n)
{
        ListD *tmp = new ListD;
        tmp->number = *n;
        if (!head)
        {
            tmp->prew = NULL;
            head = end = tmp;
        }
        else
        {
            tmp->prew = end;
            end->next = tmp;
            end = tmp;
        }
}
 
void ListD::show()
{
    wcout<< L"Вводим список на экран:\n";
    ListD *tmp(head); int i(1);
    while (tmp)
    {
        wcout <<setw(4)<< tmp->number << L" ";
        if (i == 10)
        {
            i = 0; wcout << endl;
        }
        tmp = tmp->next; i++;
    }
    wcout<< endl<<endl;
}
 
ListD ListD::replacementEvenOddNoMassiv()
{
    ListD newList;
    ListD*tmp(head);
    while (tmp)
    {
        if (tmp->number % 2 == 0) // сначала чётные
            newList.add(&tmp->number);
        tmp = tmp->next;
    }
    tmp = head;
    while (tmp)
    {
        if (tmp->number % 2 != 0) // теперь нечётные
            newList.add(&tmp->number);
        tmp = tmp->next;
    }
    return newList;
}
 
int main()
{
    _setmode(_fileno(stdout), _O_U16TEXT);
    _setmode(_fileno(stdin), _O_U16TEXT);
    // создание списка, заполнение рандмными числами и вывод на экран
    wcout << L"Введите количество элементов списка: "; int count; wcin >> count;
    ListD Number;
    for (int i(0); i < count; i++)
    {
        int number = -5 + rand() % 78;
        Number.add(&number);
    }
    Number.show();
 
    // перепись списка, сначала чётные, затем нечётные + вывод на экран
    ListD NumberNew = Number.replacementEvenOddNoMassiv(); 
    NumberNew.show();
 
    return 0;
}
Заранее спасибо за помощь.
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
19.12.2016, 01:54
Ответы с готовыми решениями:

В чём отличия конструктора копирования и конструктора перемещения? Где и как их нужно использовать?
Помогите разобраться в копирующем и перемещающем конструкторах. В чём их существенное отличие и какой плюс от использования перемещающего...

Грамотное использование кучи
искал но не нашел. ни здесь, ни где бы то ни было. вкратце: есть функция unsigned char **SubBytes(unsigned char **var) { ...

Касательно конструктора копирования
Вопрос следующий. У меня есть класс &quot;Точки&quot; есть класс &quot;группы&quot; и есть класс &quot;возможные группы&quot;. 3 класса. в классе...

9
nd2
3438 / 2817 / 1249
Регистрация: 29.01.2016
Сообщений: 9,427
19.12.2016, 02:06
Цитата Сообщение от Lagos Посмотреть сообщение
// конструктор копирования
Конструктор копирования инициализирует поля нового объекта класса (который уже создан до вызова конструктора копирования), значениями полей объекта, передаваемого в качестве параметра. Где у тебя поля нового объекта класса, созданного до вызова конструктора копирования?
0
 Аватар для Lagos
11 / 11 / 6
Регистрация: 19.01.2012
Сообщений: 195
Записей в блоге: 2
19.12.2016, 02:36  [ТС]
Вы извините, но я не понял. Слишком запутанная структура получилась.
По идее, здесь я выделил память:
ListD *tmp = new ListD;
Здесь и находятся все поля.
Далее в цикле все присваиваю.
Сомневаюсь, что это правильно.
0
nd2
3438 / 2817 / 1249
Регистрация: 29.01.2016
Сообщений: 9,427
19.12.2016, 02:38
Цитата Сообщение от Lagos Посмотреть сообщение
Здесь и находятся все поля.
Там поля того объекта, который ты создал в конструкторе копирования. А где поля того объекта (созданного до вызова конструктора копирования), для которого этот конструктор копирования и вызывается?
0
 Аватар для Lagos
11 / 11 / 6
Регистрация: 19.01.2012
Сообщений: 195
Записей в блоге: 2
19.12.2016, 02:49  [ТС]
Возможно вот:
C++
1
2
3
4
5
6
7
8
9
10
11
12
ListD(const ListD &l) // конструктор копирования
    {
        head = end = NULL;
        ListD* temp = l.head;
        while (temp)
        {
            add(&temp->number);
            temp = temp->next;
        }
        show();
        wcout << L"Сработал конструктор копирования.\n";
    }
Но здесь..по-идее, идёт обращение не к тому объекту. Как обратиться к самому первому объекту я просто не могу понять.
0
nd2
3438 / 2817 / 1249
Регистрация: 29.01.2016
Сообщений: 9,427
19.12.2016, 07:01
Лучший ответ Сообщение было отмечено Lagos как решение

Решение

Цитата Сообщение от Lagos Посмотреть сообщение
Все реализовано, но проблема в том, что в функции-члене класса создается и возвращается новый объект, с использованием конструктора копирования. Но, данные не переносятся в новый объект.
А без этого всё работает? Добавляемому узлу нужно в next ноль записывать.

Добавлено через 35 минут
Цитата Сообщение от Lagos Посмотреть сообщение
Но здесь..по-идее, идёт обращение не к тому объекту.
К тому.
Кликните здесь для просмотра всего текста
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
class ListD
{
private:
    ListD* head;
    ListD* end;
    ListD* next;
    ListD* prew;
    int number;
public:
    ListD(const ListD &l) // конструктор копирования
    {
        head = end = NULL;
        ListD* temp = l.head;
        while (temp)
        {
            add(&temp->number);
            temp = temp->next;
        }
        //show();
        cout << "Сработал конструктор копирования.\n";
    }
 
    ListD& operator=(const ListD& r)
    {
        if (this != &r)
        {
            this ->~ListD();
            
            ListD* temp = r.head;
            while (temp)
            {
                add(&temp->number);
                temp = temp->next;
            }
        
            cout << "Сработал оператор присваивания.\n";
        }
        return *this;
    }
 
    ListD()
    {
        head = end = NULL;
    }
    void add(int*);
    void show();
    ListD replacementEvenOddNoMassiv(); // метод
    ~ListD()
    {
        ListD *tmp(head);
        while (head)
        {
            tmp = tmp->next;
            delete head;
            head = tmp;
        }
        end = NULL;
    }
};
 
void ListD::add(int* n)
{
        ListD *tmp = new ListD;
        tmp->number = *n;
        tmp ->next = tmp->prew = NULL;
        if (!head)
        {
            head = end = tmp;
        }
        else
        {
            tmp->prew = end;
            end->next = tmp;
            end = tmp;
        }
}
 
void ListD::show()
{
    cout<< "Вводим список на экран:\n";
    ListD *tmp(head); int i(1);
    while (tmp)
    {
        cout <<setw(4)<< tmp->number << " ";
        if (i == 10)
        {
            i = 0; wcout << endl;
        }
        tmp = tmp->next; i++;
    }
    cout<< endl<<endl;
}
 
ListD ListD::replacementEvenOddNoMassiv()
{
    ListD newList;
    ListD*tmp(head);
    while (tmp)
    {
        if (tmp->number % 2 == 0) // сначала чётные
            newList.add(&tmp->number);
        tmp = tmp->next;
    }
    tmp = head;
    while (tmp)
    {
        if (tmp->number % 2 != 0) // теперь нечётные
            newList.add(&tmp->number);
        tmp = tmp->next;
    }
    return newList;
}
 
int main()
{
    setlocale(0, "");
    srand(time(0));
    //_setmode(_fileno(stdout), _O_U16TEXT);
    //_setmode(_fileno(stdin), _O_U16TEXT);
    // создание списка, заполнение рандмными числами и вывод на экран
    cout << "Введите количество элементов списка: "; 
    int count; 
    cin >> count;
    
    ListD Number;
    for (int i(0); i < count; i++)
    {
        int number = -5 + rand() % 78;
        Number.add(&number);
    }
    Number.show();
 
    //// перепись списка, сначала чётные, затем нечётные + вывод на экран
    ListD NumberNew = Number.replacementEvenOddNoMassiv(); 
    NumberNew.show();
    
    system("pause");
    return 0;
}

Распространенные ошибки

Добавлено через 59 минут
Список, конечно, у тебя странноватый... Каждый узел списка является объектом списка...
1
 Аватар для Lagos
11 / 11 / 6
Регистрация: 19.01.2012
Сообщений: 195
Записей в блоге: 2
19.12.2016, 09:05  [ТС]
Список, конечно, у тебя странноватый... Каждый узел списка является объектом списка...
А можно про вот это подробнее немного?
0
nd2
3438 / 2817 / 1249
Регистрация: 29.01.2016
Сообщений: 9,427
19.12.2016, 09:21
Цитата Сообщение от Lagos Посмотреть сообщение
можно про вот это подробнее немного?
Для примера:
Кликните здесь для просмотра всего текста
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
struct Node
{
    Node* next;
    Node* prev;
    int n;
};
 
struct List
{
    Node* head;
    Node* end;
 
    List() : head(nullptr), end(nullptr)
    {}
 
    List(const List& r) : head(nullptr), end(nullptr)
    {
        Node* temp = r.head;
        while (temp)
        {
            add(temp ->n);
            temp = temp ->next;
        }
    }
 
    void add(int m)
    {
        Node* nod = new Node;
        nod ->n = m;
        nod ->prev = nod ->next = nullptr;
        
        if (head == nullptr)
            head = end = nod;
        else
        {
            end ->next = nod;
            nod ->prev = end;
            end = nod;
        }
    }
 
    List& operator=(const List& r)
    {
        if (this != &r)
        {
           this ->~List();
            
            Node* temp = r.head;
            while (temp)
            {
                add(temp ->n);
                temp = temp ->next;
            }
        }
        return *this;
    }
 
    void show()
    {
        Node* cur = head;
        while (cur)
        {
            std::cout << cur ->n << ' ';
            cur = cur ->next;
        }
        std::cout << std::endl;
    }
 
    ~List()
    {
        Node* temp;
        while (head)
        {
            temp = head ->next;
            delete head;
            head = temp;
       }
       end = nullptr;
    }
};
 
 
int main()
{
    List listA;
    const int N = 5;
    for (int i = 0; i < N; ++i)
        listA.add(i + 1);
    
    listA.show();
 
    List listB(listA);
    listB.show();
    
    List listC;
    for (int i = 0; i < N + 3; ++i)
        listC.add(i + 10);
    
    listB = listC;
    listB.show();
    
    system("pause");
    return 0;
}
1
 Аватар для Lagos
11 / 11 / 6
Регистрация: 19.01.2012
Сообщений: 195
Записей в блоге: 2
19.12.2016, 14:52  [ТС]
Спасибо за пример! Отныне буду данные, и предыдущий с следующим элементом хранить в структуре, а все остальное - в классе.

Добавлено через 26 минут
Долго не мог понять, почему метод show() идёт дальше. В итоге, дошло. Создал в структуре конструктор, который обнулял значение указателей предыдущего и следующего элементов. Вот итоговый код:
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
struct Node // структура хранит данные и след. + пред. элементы
{
    Node() :next(NULL), prew(NULL) {}; // вот здесь была проблема
    Node* next;
    Node* prew;
    int number;
};
 
class ListD
{
private:
    Node* head;
    Node* end;
public:
    ListD() :head(nullptr), end(nullptr) {}
    ListD(const ListD &l):head(nullptr), end(nullptr) // конструктор копирования
    {
        Node* temp = l.head;
        while (temp)
        {
            add(&temp->number);
            temp = temp->next;
        }
        wcout << L"Сработал конструктор копирования.\n";
    }
 
    ListD& operator=(const ListD& r) // перегрузка оператора ==
    {
        if (this != &r)
        {
            this ->~ListD();
 
            Node* temp = r.head;
            while (temp)
            {
                add(&temp->number);
                temp = temp->next;
            }
            cout << "Сработал оператор присваивания.\n";
        }
        return *this;
    }
    void add(int*);
    void show();
    ListD replacementEvenOddNoMassiv(); // метод
    ~ListD()
    {
        Node *tmp(head);
        while (head)
        {
            tmp = tmp->next;
            delete head;
            head = tmp;
        }
    }
};
 
void ListD::add(int* n)
{
        Node *tmp = new Node;
        tmp->number = *n;
        if (!head)
        {
            tmp->prew = nullptr;
            head = end = tmp;
        }
        else
        {
            tmp->prew = end;
            end->next = tmp;
            end = tmp;
        }
}
 
void ListD::show()
{
    wcout<< L"Вводим список на экран:\n";
    Node *tmp(head); int i(1);
    while (tmp)
    {
        wcout <<setw(4)<< tmp->number << L" ";
        if (i == 10)
        {
            i = 0; wcout << endl;
        }
        tmp = tmp->next; i++;
    }
    wcout<< endl<<endl;
}
 
ListD ListD::replacementEvenOddNoMassiv()
{
    ListD newList;
    Node*tmp(head);
    while (tmp)
    {
        if (tmp->number % 2 == 0) // сначала чётные
            newList.add(&tmp->number);
        tmp = tmp->next;
    }
    tmp = head;
    while (tmp)
    {
        if (tmp->number % 2 != 0) // теперь нечётные
            newList.add(&tmp->number);
        tmp = tmp->next;
    }
    return newList; // нужен конструктор копирования
}
 
int main()
{
    _setmode(_fileno(stdout), _O_U16TEXT);
    _setmode(_fileno(stdin), _O_U16TEXT);
    srand(time(0)); // для случайной рандомности
    // создание списка, заполнение рандомными числами и вывод на экран
    wcout << L"Введите количество элементов списка: "; int count; wcin >> count;
    ListD Number;
    for (int i(0); i < count; i++)
    {
        int number = -5 + rand() % 78;
        Number.add(&number);
    }
    Number.show();
    // перепись списка, сначала чётные, затем нечётные + вывод на экран
 
    ListD NumberNew = Number.replacementEvenOddNoMassiv();
    NumberNew.show();
 
    return 0;
}
Огромное Вам спасибо за srand(time(0)). Давно искал, никак не мог найти. Теперь хотя бы почитаю по-подробнее про это.
И ещё, хотелось бы узнать, почему nullptr? Помню, данное значение использовалось в .Net, там NULL попросту нет, если я не ошибаюсь.
Ещё раз спасибо!
0
nd2
3438 / 2817 / 1249
Регистрация: 29.01.2016
Сообщений: 9,427
20.12.2016, 01:06
Цитата Сообщение от Lagos Посмотреть сообщение
Долго не мог понять, почему метод show() идёт дальше. В итоге, дошло.
Если ты насчёт кода в первом посте, то я же писал об этом:
Цитата Сообщение от nd2 Посмотреть сообщение
Добавляемому узлу нужно в next ноль записывать.
Цитата Сообщение от Lagos Посмотреть сообщение
И ещё, хотелось бы узнать, почему nullptr? Помню, данное значение использовалось в .Net,
http://www.cplusplus.com/refer... nullptr_t/
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
20.12.2016, 01:06
Помогаю со студенческими работами здесь

Неявный вызов конструктора копирования
Здравствуйте, как можно неявно вызвать конструктор копирования 3 способами? Я только 1 найти смог. #include &lt;iostream&gt; ...

Ошибка в перегрузке конструктора копирования
// strimem.cpp // Класс String с экономией памяти // Перегружаемая операция присваивания и конструктор // копирования #include...

По поводу ссылок и конструктора копирования
Никак не пойму. При создании объекта и передачи конструктору в качестве параметра объекта другого класса, отладчик показывает что на...

Подскажите реализацию конструктора копирования
Подскажите пожалуйста как реализовать конструктор копирования. #include &lt;iostream&gt; #include &lt;stdio.h&gt; #include &lt;math.h&gt; ...

Реализация конструктора копирования и перегрузки =
#include &lt;iostream&gt; #include &lt;cstring&gt; using namespace std; class Cow{ private: char name; char *...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
Первый деплой
lagorue 16.01.2026
Не спеша развернул своё 1ое приложение в kubernetes. А дальше мне интересно создать 1фронтэнд приложения и 2 бэкэнд приложения развернуть 2 деплоя в кубере получится 2 сервиса и что-бы они. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит токи на L и напряжения на C в установ. режимах до и. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
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
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru