Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.88/48: Рейтинг темы: голосов - 48, средняя оценка - 4.88
0 / 0 / 0
Регистрация: 14.03.2013
Сообщений: 3
1

Возврат объекта класса из функции

14.03.2013, 19:56. Показов 9769. Ответов 7
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Имеется следующий код:

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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include "stdafx.h"
#include <iostream>
using namespace std;
 
/*Задача:
Определить класс список элементов. В определение класса включить два конструктора для определения списка 
по его размеру и путем копирования другого списка.
Определить операции над списком:
[ ] получение значения информационного поля указанного элемента списка;
–    удаление из первого списка элементов второго, если второй список входит в первый.
*/
 
//Прототип класса
class List
{
    public:
        void Print();
        List (int);
        List (const List&);
        ~List();
        int operator [] (int);
        List operator - (List);
    private:
        int size;
        struct list
        {
            int data;
            list *next;
        };
        list *head;
};
 
 
//Конструктор, создающий список по его размеру
List::List(int sz)
{
    size=sz;
    head=NULL;
    List::list *p,*t;
    for (int i=0;i<sz;i++)
    {
        p=new List::list;
        p->data=rand()%100;
        if (head==NULL) 
        {
            head=p;
            head->data=p->data;
        }
        else {t->next=p;}
        t=p;
        p->next=NULL;
    }
}
 
//Конструктор, создающий копию существующего списка
List::List(const List& l)
{
    head=NULL;
    size=0;
    List::list *src=l.head,*p,*tl;
    while (src)
    {
        p=new List::list;
        p->data=src->data;
        p->next=NULL;
        if (head==NULL) 
        {
            head=p;
            head->data=p->data;
        }
        else {tl->next=p;}
        tl=p;
        src=src->next;
        size++;
        p->next=NULL;
    }
}
 
//Деструктор, удаляющий элементы списка
List::~List()
{
    List::list *p;
    for (int i=0;i<size;i++)
    {
        p=head;
        head=head->next;
        delete p;
    }
    cout<<"something has been destructed"<<endl;
}
 
//Функция вывода списка на экран
void List::Print()
{
    List::list *p=head;
    while(p)
    {
        cout<<p->data<<" ";
        p=p->next;
    }
    cout<<endl;
}
 
//Перегрузка операции [] - возврат значения указанного элемента списка
int List::operator [] (int n)
{
    list *p=head;
    for (int i=1; (i<n)&&(p!=NULL); i++, p=p->next);
    if (p) return p->data;
    return -1;
}
 
//Перегрузка бинарного оператора "-" - удаление из первого списка элементов второго, если второй список входит в первый.
List List::operator - (List l2)
{
    List temp(0);
    cout<<"temp object created"<<endl;
    temp.head=NULL;
    temp.size=0;
    bool contains;
    list *p1=this->head,*p2=l2.head,*p=temp.head,*t=NULL;
    while (p1)
    {
        contains=false;
        cout<<"p1 data"<<p1->data<<endl;
        while (p2)
        {
            cout<<"p2 data: "<<p2->data<<endl;
            if (p1->data==p2->data) {contains=true;}
            p2=p2->next;
        }
        if (contains==false)
        {
            p=new List::list;
            p->data=p1->data;
            p->next=NULL;
            if (temp.head==NULL) 
            {
                temp.head=p;
                temp.head->data=p->data;
            }
            else {t->next=p;}
            t=p;
            temp.size++;
            cout<<endl<<"writed something into the temp object: "<<p->data<<endl;
            p=p->next;
        }
        p2=l2.head;
        cout<<"p1data"<<p1->data<<endl;
        p1=p1->next;
    }
    return temp;
}
 
//Главная функция программы
void main()
{
    int number;
    cout<<"Enter number of elements:";
    cin>>number;
    List list1(number),list2(list1),list3(0);
    cout<<endl<<"Generated list:"<<endl;
    list1.Print();
    cout<<"Copy-constructor:"<<endl;
    list2.Print();
    cout<<"Enter number of element:";
    cin>>number;
    cout<<endl<<"Element #"<<number<<" is: "<<list1[number]<<endl<<" (if = -1 -- wrong number entered)"<<endl;
    
    List list4(5);
    cout<<endl<<"Generated 4th list (contains 5 nodes):"<<endl;
    list4.Print();
 
    cout<<endl<<"Overloaded operator '-' result: list3=list1-list4"<<endl;
    list3=list1-list4;
    list3.Print();
    cout<<"main() ended"<<endl;
}
Собственно, такое впечатление, что по выходу из функции (перегруженный бинарный минус), созданный внутри объект уничтожается, и попытка запустить функцию вывода в консоль содержимого объекта вешает программу. Деструктор также не отрабатывает как положено. В чём моя ошибка? И как исправить?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
14.03.2013, 19:56
Ответы с готовыми решениями:

Создание объекта в функции и возврат объекта из нее
Не могу разобраться с ссылками. Возможно ли вернуть из функции объект созданный в стеке при этом...

Виртуальная функция и возврат объекта класса
Доброго времени суток! Столкнулся с проблемой. Есть переопределенный оператор умножения в...

Возврат объекта из функции
Здравствуйте. Написал в Code.Blocks на C++ вот такой код (привожу только часть кода, остальное на...

Возврат моего объекта List из функции
Ребята, вот есть у меня такой List: template&lt;class T&gt; class List { public: typedef T*...

7
...
1906 / 1326 / 965
Регистрация: 12.02.2013
Сообщений: 2,172
15.03.2013, 09:39 2
Замечания:
  1. Строка 19: Передавать желательно по ссылке, а не по значению. В результате передачи по значению, создаётся копия объекта, т.е. вызывается конструктор копирования.
  2. Строка 175: А вы перегружали оператор '='? Естественно нет, в этом и заключается ваша основная ошибка. Проблема в том, что результатом операции '-' вы получили временный объект, и время его жизни закончится после выполнения данной операции, что приведёт к вызову деструктора. А при отсутствии перегрузки присвоения все значения (size и head) временного объекта тупо скопируются в list3, т.е. указатель head будет указывать уже на удалённую область. А по завершению программы вызывается деструктор list3. И что по вашему он должен удалять? Кроме всего изложенного этим действием вы можете спровоцировать утечку памяти, в случае если list3 имел уже какие-либо значения. Т.е. вы должны либо перегрузить '=', либо инициализировать list3 в момент выполнения операции '-', что в свою очередь вызовет конструктор копирования.
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#include <iostream>
#include <cstdlib>
#include <ctime>
 
using namespace std;
 
/*Задача:
Определить класс список элементов. В определение класса включить два конструктора для определения списка
по его размеру и путем копирования другого списка.
Определить операции над списком:
[ ] получение значения информационного поля указанного элемента списка;
–    удаление из первого списка элементов второго, если второй список входит в первый.
*/
 
//Прототип класса
class List
{
   public:
      void Print();
      List(int size = 0);
      List(const List&);
      ~List();
      int operator [](int);
      List operator - (const List&) const;
 
   private:
      int size;
      struct list
      {
         int data;
         list* next;
      };
      list* head;
};
 
 
//Конструктор, создающий список по его размеру
List::List(int sz): size(sz), head(NULL)
{
   List::list* t = NULL;
   for (int i = 0; i < sz; i++)
   {
      List::list* p = new List::list;
 
      p->data = rand() % 100;
      p->next = NULL;
 
      if (head == NULL)
      {
         head = p;
      }
      else
      {
         t->next = p;
      }
      t = p;
   }
}
 
//Конструктор, создающий копию существующего списка
List::List(const List& l): size(0), head(NULL)
{
   size = l.size;
 
   List::list* tl = NULL;
   for (List::list* src = l.head; src; src = src->next)
   {
      List::list* p = new List::list;
      p->data = src->data;
      p->next = NULL;
 
      if (head == NULL)
      {
         head = p;
      }
      else
      {
         tl->next = p;
      }
      tl = p;
   }
}
 
//Деструктор, удаляющий элементы списка
List::~List()
{
   while (head)
   {
      List::list* p = head;
      head = head->next;
      delete p;
   }
 
   cout << "something has been destructed" << endl;
}
 
//Функция вывода списка на экран
void List::Print()
{
   List::list* p = head;
   while (p)
   {
      cout << p->data << " ";
      p = p->next;
   }
   cout << endl;
}
 
//Перегрузка операции [] - возврат значения указанного элемента списка
int List::operator [](int n)
{
   list* p = head;
 
   for (int i = 1; (i < n) && p; ++i, p = p->next) { ; }
 
   return p ? p->data : -1;
}
 
//Перегрузка бинарного оператора "-" - удаление из первого списка элементов второго, если второй список входит в первый.
List List::operator - (const List& l2) const
{
   List temp;
   cout << "temp object created" << endl;
   bool contains;
   list* p1 = this->head, *p2 = l2.head, *p = temp.head, *t = NULL;
   while (p1)
   {
      cout << "p1 data" << p1->data << endl;
 
      contains = false;
      while (p2 && !contains)
      {
         cout << "p2 data: " << p2->data << endl;
         contains = (p1->data == p2->data);
         p2 = p2->next;
      }
 
      if (contains == false)
      {
         p = new List::list;
         p->data = p1->data;
         p->next = NULL;
         if (temp.head == NULL)
         {
            temp.head = p;
         }
         else
         {
            t->next = p;
         }
         t = p;
         temp.size++;
         cout << endl << "writed something into the temp object: " << p->data << endl;
         p = p->next;
      }
      p2 = l2.head;
      cout << "p1data" << p1->data << endl;
      p1 = p1->next;
   }
   return temp;
}
 
//Главная функция программы
int main()
{
   int number;
   cout << "Enter number of elements:";
   cin >> number;
 
   List list1(number);
   List list2(list1);
 
   cout << endl << "Generated list:" << endl;
   list1.Print();
 
   cout << "Copy-constructor:" << endl;
   list2.Print();
 
   cout << "Enter number of element:";
   cin >> number;
   cout << endl << "Element #" << number << " is: " << list1[number] << endl << " (if = -1 -- wrong number entered)" << endl;
 
   List list4(5);
   cout << endl << "Generated 4th list (contains 5 nodes):" << endl;
   list4.Print();
 
   cout << endl << "Overloaded operator '-' result: list3=list1-list4" << endl;
   List list3 = list1 - list4;
   list3.Print();
 
   cout << "main() ended" << endl;
 
   return 0;
}
1
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
15.03.2013, 10:38 3
Цитата Сообщение от anmartex Посмотреть сообщение
Строка 19: Передавать желательно по ссылке, а не по значению.
Цитата Сообщение от random123 Посмотреть сообщение
List (const List&);
Так ведь и передается по ссылке.
2
...
1906 / 1326 / 965
Регистрация: 12.02.2013
Сообщений: 2,172
15.03.2013, 10:44 4
Tulosba, да, верно! Блин, помню, что проблема с ссылкой была, но не то указал . Строка 114, там нет ссылки, а не в конструкторе копирования. Спасибо, что поправили.
1
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
15.03.2013, 10:58 5
Цитата Сообщение от anmartex Посмотреть сообщение
Строка 114, там нет ссылки
Более того, ссылка должна быть const (ведь мы не изменяем l2). И сам метод тоже должен быть const (т.к. не изменяется this).
1
...
1906 / 1326 / 965
Регистрация: 12.02.2013
Сообщений: 2,172
15.03.2013, 10:59 6
Tulosba, однозначно! В моёй версии она там есть
Как я мог промазать, вообще хотел только в прототипе указать ошибку и промахнулся, вместо строки 22 указал 19
1
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
15.03.2013, 11:05 7
anmartex, до кучи ещё в operator[] добавить const. Вместо NULL использовать nullptr, и вообще заменить список на std::list
2
...
1906 / 1326 / 965
Регистрация: 12.02.2013
Сообщений: 2,172
15.03.2013, 11:10 8
Цитата Сообщение от Tulosba Посмотреть сообщение
anmartex, до кучи ещё в operator[] добавить const. Вместо NULL использовать nullptr, и вообще заменить список на std::list
Угу
1
15.03.2013, 11:10
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
15.03.2013, 11:10
Помогаю со студенческими работами здесь

Возврат и присвоение объекта из функции без копирования
Возможно ли в С++ вернуть объект (то есть записать данные объекта) напрямую в область памяти,...

Возврат из функции ссылки на экземпляр класса
Здравствуйте, прошу помочь в разъяснении не понятной конструкции.Искал в интернете не нашел ничего...

Возможно ли создание объекта шаблонного класса в функции этого класса?
Доброго времени суток, уважаемые форумчане :) Мне по лабам задали задание - реализовать шаблон...

Возврат объекта определенного класса в методе через условие
День добрый, дорогие форумчане! Сразу хочу извиниться, если тема есть и не нашел ее. Просто...


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

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru