Реализация односвязного списка c++ Часть 1 | Урок
HTML-код
- Опубликовано: 7 сен 2024
- В этом уроке мы начнём писать собственный односвязный список на языке программирования C++ с подробными пояснениями.
Односвязный список | Динамические структуры данных #1
Теория goo.gl/E5KrVi
Определение методов вне класса. Вынести функцию в из класса. Вынести описание метода вне класса. #89
goo.gl/gqh536
Шаблоны классов с++ примеры. Обобщенные классы. Изучение С++ для начинающих. Урок #126
goo.gl/U99h9t
✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅
Если вам нравятся мои уроки, вы хотите поддержать меня и развитие канала, то можете сделать это тут!=)
🔴🔴🔴 www.donationale...
или тут
🔴🔴🔴 / simplecode
✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅
Уроки по программированию
Наша группа ВК smplcode
Подписывайтесь на канал / @simplecodeit
Спасибо вам большое. Я сама студентка и нам сказали лабы писать на С++, теперь вся група смотрит вас и учиться. Вы хорошо рассказываете, понятно. Спасибо.
Пожалуйста!
+
@@SimpleCodeIT Сергей, подскажите, пожалуйста, в каком уроке появился синтаксис типа "current->pnext" или "current-> data" 20:34
@@user-mm8hc5uu1e Урок про указатель this №94.
Коротко: с прототипа класса к полям обращаемся через точку, с указателя через ->
Node current;
current.pNext;
Node *current;
current->pNext;
храни тебя господь, долгих тебе лет жизни, спасибо за огромнейший труд, на твоем канале довольно давно сижу, всю процедурку вместе с тобой прошел, почти все ООП, понял как работает односвязный список, спасибо тебе огромное, настоящий учитель)))))))))
Очень полезный урок. Ребят, если вы переписывайте код, то не забывайте его комментировать во-первых для того, чтобы самому лучше понять как и что работает, а во-вторых, чтобы при просмотре вашего кода, например через месяц, вы не путались в огромном количестве строк кода.
А также не забывайте комментировать и ставить лайки под такими видео, чтобы увеличить их популярность.
Памятник при жизни Сергею поставлю!!! Спасибо вам Сергей за ваши труды, здоровья вам и вашим близким, долгих лет жизни, и хороших людей рядом!!!
Спасибо за урок! Для учащихся - в процессе урока пишите код, на не понятных моментах делайте паузы и перебирайте код отладчиком или глазами, так легче мозг принимает информацию.
*Cамый лучший способ сказать "спасибо" - поставить лайк и и поделиться уроком с друзьями. Это очень мотивирует создавать полезные уроки =)*
Зачем создавать шаблонный Node, когда он и так объявлен в шаблонном List. Тип T для всех будет один, разве нет?
нет
Миша Якименко я проверил, лишний шаблон не нужен
@@borisshabanov6702 у меня тоже так сработало, не пойму смысла Node делать шаблонным. В code::blocks вообще ошибку выдает.
Более того компилятор не запускает программу , так как не может понять параметр T, я пишу в code blocks, может в studio по другому
Я не знаю, как бы я изучил ЭТО без таких прекрасных объяснений. Это шедевр
ну ты дал, Сергей!:)) загрузил так загрузил:) самое удивительное, что я все понял, а я новичок в этом) Спасибо! и присоединяюсь про бабосы с первой зп. Это заслуженно 100%.
Не описать словами чувство удовлетворения от понимания устройства односвязного списка после ваших разъяснений! Спасибо большое!
Вообще не знаю, как бы я понимал программирование без Сергея. Спасибо, друг.
Спасибо за столь не простой урок. По уровню сложности я бы его оценил как урок про конструкторор копирования. Однако, пересматривая урок по несколько раз с каждым разом, понимание становится лучше и лучше.
Обещаю часть своей первой зарплаты (от работы програмиста) отправить вам на поддержку канала!
Присоединяюсь, отличная идея!
peace да ball
@Artur Golovenko Тебе так хочется верить. Я отучился на программиста, за 5 лет обучения я знаю меньше чем с уроков ютуба(т.к там преподу пофигу знаешь ты или нет. Он приходит сидит там мямлет что то себе под нос, читая слайд шоу. На ютубе ты можешь выбрать канал, а препода в универе нет.При обучении я просто ненавидил с++.) Конечно нужно еще почитать кое какой инфы и книг, много гуглить, много проб и ошибок. Этот диплом, что я получил мне абсолютно никакой пользы не принес. Работаю не по специальности. Данная работа мне приносит, для моего опыта и возраста колоссальный доход ,какие то цифры я приводить не буду, дабы тут не хвастаться не перед кем. Но у данной моей работы есть огромные минусы. Она очень тяжелая, много грязи, и еще связана с командировками(причем бывают и по пол года). Поэтому я решил вернуться к истокам с чего и начинал, к программированию. Смотря курс Сергея(ему огромное отдельное спасибо!!!!). Я постиг много во, теперь действительно могу что то написать. Читаю книги Бьерна Страуструппа, все свое свободное время просто вкладываю в обучение. Учу параллельно английский. Главное вера в себя, хорошая усидчивость, голова на плечах и руки не из одного места:) Сергею еще раз большое спасибо, из всех просмотренных мной каналов это самый лучший. Он действительно хорошо все объясняет, как говорят, нам все разжевал - осталось только в рот положить. По сравнению с тем же Дударем(давайте создадим переменную, а хотя можно и не создавать) - его смотреть это когда все знаешь.
@@iii-mk7no Ну, как бы суть современного высшего образования в том, что тебе указывают нужное направление, а дальше ты сам в интернете и библиотеках учишься.
@@jojomajo 1) Російська мова не є моя рідна 2) Гроші я переказав, можеш спитати у автора 3) Зараз працюю в Європі айтішніком :) За допомогою цього вже всю Європу об'їздив, фотки вислати?)
3 часа бился над ошибкой, почему не выводит результат lst[2], при этом забыв завести команду lst.push_back(22). Только отладчиком понял, что условие if не возвращает результат, потому что 3 переменную листа не завёл)) Кстати в кодблокс пришлось у Node делать тип T1, иначе не работает. Спасибо комментариям снизу. Тема обсуждалась, когда число подписчиков было 10 тыс, а я смотрю когда уже 233 тыс. Спасибо, Сергей за отличные уроки. Надеюсь через год переквалифицируюсь из инженера-конструктора в программисты.
Мы создаём объект List. Внутри объекта лист счётчик и капсула Node с адресом следующей капсулы и данными. Функция push_back создаёт указатель на первую капсулу. Если адрес следующей капсулы равен нулю, то в переменной pNext мы создаём новую капсулу, если же там есть адрес то мы перебираем все адреса путём присваивания из капсулы head параметра pNext следующего адреса в переменную current. И так пока адрес следующей капсулы не будет равен 0. И опять же дойдя до этого элемента присваиваем в параметр pNext следующую капсулу. 3 дня ушло чтобы это всё понять)
Привет а зачем нужно создавать временный указатель(current) ?
@@user-oo9tn8fj7i она типа временная, я тоже задался этим вопросом. Попробовал сделать без нее используея this->head ну и это даже не компилилось)
Это позволяет, я так понял, обращаться по очереди к каждому адресу это в случае перегрузки operator[], а в PushBack() это позволяет последовательно создавать новые элементы списка. Трудно объяснить к сожалению, но отладчиком все хорошо можно проследить)
По сути в этом нет ничего сложного, просто столько времени уходит на понимание, потому что никто не умеет нормально объяснять, выделяя основную суть что и зачем делается. Что автор, который заваливает кодом, нежели говорит суть, что этот комментарий, под которым я пишу, в котором уровень пунктуации на крайне печальном уровне. Из-за этого вполне простые вещи в голове разбрасываются в хаотичном порядке, и становится сложнее втройне, просто потому что людям не дано нормально объяснять
@@nick-ei2og Сказал человек, который растянул мысль на целый параграф)))
@@user-oo9tn8fj7i Указатель current мы создаём потому что он перебирает все элементы, тем самым присваивая себе эти элементы по очереди, пока не дойдёт до последнего элемента и дальше не создаст новый(речь идёт о Push_Back), а head нельзя изменять потому что это начальный элемент
Господи это реально лучший канал по си плюсам, Чувак ты лучший❤️❤️❤️
Не знаю как в VS17 а в VSCode и компиляторе g++, чтобы исключить ошибку декларирования
("error: declaration of template parameter 'T' shadows template parameter") можно писать так:
template
class List
{
private:
template //Т - ненадо объявлять, т.к. переменная объявлена ранее
class Node
{
public:
Node *pNext;
T data;
Node(T data = T(), Node *pNext = nullptr)
{
this->data = data;
this->pNext = pNext;
}
};
Node *head;
int Size;
public:
List(/* args */);
~List();
void push_back(T data);
int GetSize() { return Size; }
T &operator[](const int index);
};
Огромное спасибо. Очень выручил!
Спасибо большое Сергей за реализацию списка!
Для тех кто не понял как работает pNext:
while просматривает значение current->pNext, если оно не nullptr то берет значение адреса памяти следущего елемента.
а присваиваеться это следущее значение текущему в функции push_back этими строчками:
Node* current = this->head;//создаеться указатель на первый указатель класса
если у первего указателя переменная pNext = null; то создаеться новый екземпляр класса Node с pNext = null, а pNext у head(если изменить значение у указателя то значение основного обьекта также смениться) становиться равным адрессу памяти нового екземпляра при помощи:
current->Nextptr = new Node(data);
и так можно добавлять елементы до бесконечности, каждый елемент будет хранить указатель на следущий
этот чувак просто гений у него есть настоящий дар учителя потрясающий контент!
Спасибо!
видео класс, жду уроков про очередь и бинарное дерево)
Уважаемый, Сергей! 10к подписчиков, с чем я вас сильно поздравляю=). Надеюсь ролик о том, как вы стали программистом монтируется(просто не терпится послушать).
Спасибо! Я всё помню, ролик будет завтра.
Я устал пересматривать этот урок. Уже сотый раз прохожу отладчиком по коду, чтобы уяснить логику. В прошлый раз такая же проблема была на перегрузке конструктора копирования. Осилил его - осилю и этот. Сергей ты лучший
Спасибо за урок
В очередной раз огромная благодарность Вам за доходчивое разъяснение и внятный, толковый пример.
Просто безумно интересно, продолжай в таком же духе Сергей!!! От меня лайк.
#односвязныйсписок #динамическиеструктурыданных #SimpleCode #урокипрограммирования
Разобрал я этот пример и подумал про себя а умно все это сделано=)
Блин, ну вроде бы понял как это всё работает, спасибо Сергею за такой труд)
Огромное спасибо! Отличные, понятные, содержательные уроки. Очень полезно!
Спасибо за урок!
Спасибо за разъяснение.Всё толково и понятно!❤
чего добился за эти 5 мес?
@@Hikikomori123всё работает хорошо.Список у меня из структур.Хотел что бы происходила сортировка по какой либо записи структуры,но пока не знаю как используя стандартные средства среды это сделать?
У вас в плейлисте "Основы C++. Программирование для начинающих" не хватает теории про односвязный список. (то что ссылка в описании видел)
и весь остальной плейлист про динамические структуры данных
Ловите мой вариант функции push_back
void List::push_back(T info)
{
if (tail == NULL)
tail = head = new Node(info, head);
else
tail = tail->next = new Node(info);
size++;
}
в этом варианте в классе должен быть еще Node*tail, который всегда будет находиться в самом низу списка (он все еще односвязный), tail->next всегда = NULL. Такой вариант кода позволяет не пробегать по всему списку каждый раз, когда элемент надо добавить вниз.
Я думаю объект типа T в функцию push_back надо передавать по ссылке, а не по значению.
А то получается ты копируешь объект 3 раза: из main в push_back, из push_back в конструктор Node и из конструктора Node в переменную data класса Node
Сегодня на собесе загрузили по данной теме, хотя опыт 20 лет на сях. Всегда есть чему учится.
Может кому-то будет изначально не понятно как и мне. Указатель head содержит адрес по которому одновременно хранятся данные + указатель на следующий элемент. Соответственно когда в функции push_back мы создаем указатель current то в него попадает, то что лежит по первому элементу List (это два поля данные и указатель(который, для случая, что у нас только 1 элемент листа все еще равен nullptr). Затем мы в поле указателя ячейки листа у которой поле указателя на следующий элемент равно nullptr присваиваем адрес данных (новая ячейка) которую мы функцией Push_back добавляем.
классный урок, спасибо Сергей!
Спасибо большое за урок. Преподы не могут так объяснить как вы!)
Пришел из курса по C#. Тема Рекурсия. Плюсы таки сложнее шарпа, но смотреть интересно. Автор канала крут!
очень интересно
Классное видео! Кстати можно было избежать цикла while при добавлении не первого элемента в push_back, например, объявив Node* last рядом с head и далее использовать в push_back.
Данная программа не компилируется, выдается ошибка (declaration of template parameter 'T'). Проверил в нескольких компиляторах везде одна и та же ошибка. Как её решить? А главная, почему программа в ролике вообще компилируется ???????????????
Спасибо за бесценный труд!)
Огромное спасибо !!!!
Спасибо за урок.
спасибо большое, очень понравился урок, продолжай в том же духе!!!
Спасибо за отличный урок!
Спасибо за уроки, Сергей! Надеюсь еще читаете эти комментарии.
Такой вопрос:
Решил после просмотра серии уроков про список, написать самостоятельно по полученным знаниям свой класс списка. И на моменте описания перегрузки оператора [ ] у меня получились расхождения с вами.
В моем случае я эту перегрузку описал так:
template
T& List::operator[](int index)
{
int counter = 0;
Node* current = head;
while (counter != index)
{
current = current->pNext;
counter++;
}
return current->data;
}
Подскажите, как мне кажется мой вариант более компактный, однако он допускает значения индекса больше, чем список имеет значений. И в случае превышения индекса программа завершается с ошибкой, как это было бы с обычным массивом, выйдя за его пределы. В вашем же случае, при выходе за границы результат всегда будет 0.
Помню вы говорили, что лучше если программа завершится с ошибкой, чем выдаст какое-то значение, из-за которого дальнейшая работа будет некорректна и мы устанем искать причину такого поведения.
Собственно вопрос, как лучше описывать эту перегрузку?)
Node *current = this->head;
for (int i = 0; i < index; i++)
{
current = current->pNext;
}
return current->data;
Я описал это вот так. Но в моём случае при отрицательном значении индекса оператор возвращает первый элемент списка. Но не думаю, что это большая проблема
я целых часов 5 наверное сидел и перетирал что вообще происходит(в частности с тем откуда 2 поля(pNext) у 1 переменной )
Это просто нереально полезный для меня урок
спасибо чувак.. сними уроки для c#. буду благодарен
Было бы неплохо добавить указатель на последний элемент этого списка, т.к. при больших значениях узлов такого списка, его создание займёт огромное количество времени
спасибо
в реализации оператора индексации, после цикла while желательно написать обработку ситуации, когда индекс меньше количества элементов. Т.е.
while(current!=nullptr) выполнится раньше, чем найдем индекс.
Обычно компиляторы такой код не компилят, но х3. Спасибо, брооо
а не должно быть - while(current->Nextptr != nullptr) ?
По-моему намного выгоднее завести отдельный указатель на конец списка (tail) и без этого цикла сразу полю next этого указателя присваивать новый node. И затем просто переставить указатель на конец списка этому новому node.
if (head == nullptr) {
head = new node(elem);
tail = head;
}
else {
tail->next = new node(elem);
tail = tail->next;
}
Very available explained!Like!
Благодаря вам сдала лабу по программе, большое спасибо ~
Ну push_back можно было бы оптимизировать. Просто в list хранить ещё и указатель на последний элемент. Далее мы в поле последнего элемента приравниваем новый указатель new Node (data), после чего просто в указатель в List мы приравниваем вновь созданный указатель
Серега спасибо!
Урок предельно понятный и информативный, но нужно еще и самому всё это написать и пробежаться отладчиком.
большое спасибо за урок!!! Удачи Вам) а каналу 500К подписчиков!!!
Кстати. Запустил прогу, вписал 50 тыщь, и консоль затупила)) Теперь я понял в чем разница списка и массива. Массив быстрее работает с большими индексами.
Ахахахах, тоже показательный пример
Спасибо за урок, но было бы лучше, если на простые вещи было бы меньше акцента, а на более сложные - больше.
Отличный курс!!!!!!!!!!!!!!!!!
Мощно)2 ой день уже смотрю)
невозможно преобразовать аргумент 1 из "Т" в "List::Node *"
Нашёл решение?
@@Andrey-qj9sjнет
поміняй місцями параметри в класі нут в круглих дужках
спочатку напиши T data=T() а потім Node *pNext
@@oljaolsa7261 Вы серьезно думаете что все знают укр язык?
Код целиком скинь
безмерная благодарность Тебе
даужь, начались наконец то уроки по сложнее
Thank you for the lesson!
Автору огромное спасибо за урок! Скажите, пожалуйста, обязательно ли внутренний класс Node делать шаблонным? Ведь и класс List, и класс Node всегда будут работать с одинаковыми типами данных.
Главное, что определение методов внутри определения класса делает их встроенными, что не нужно в большинстве случаев. А уже потом это загромождает код.
мозг кипит)
Ребят, кто не понял, как так происходит присвоение, в конструкторе:
Node(T data = T(), Node* pNext = nullptr)
Тут прикол идёт прямиком из урока про параметры функций по умолчанию. Когда вы задаёте параметру присваивание, то вы тем самым, в этой функции можете не передавать данных, тогда функция по умолчанию выдаст то, что вы присвоили в параметрах. Например:
void Foo(int a = 5). Это означает, что если вы напишете Foo()- не передадите каких-либо параметров, то парметр "а" в Foo(int a = 5), приймет значение 5. Если же вы впишете Foo(6), то "а" будет == 6. Я только сейчас понял, как работает конструктор Node.
Хоть ты что-то объяснил, а то этот об.мудок из видео при объяснении чего-то сложнее 2+2 плывёт и переходит на долгое объяснение очевидных вещей
@@user-ln2qd8sy9z Я лишь на 3-ей части реализации списка лишь понял, как оно работает. У меня так с конструктором копирования было, пока не посмотрел как сделать конструктор присваивания
Вот смысл лезть в такие темы как реализация динамической структуры данных, когда не знаешь такой базовой вещи как параметр по умолчанию? 🤨
@@sleepyNovember_project Ну в этом и заключается прелесть обучения, когда ты можешь найти ответ сам.
Если выдает ошибку "error: declaration of template parameter 'T' shadows template parameter", то попробуйте назвать параметры по-разному: например T для class List и T1 для class Node.
Что-то все-равно не идет, та же ошибка
бл... я Т по ходу кириллицей писал! Теперь все норм.
Сергей, привет! Спасибо за реализацию списка! Это твоё первое видео такой внушительной продолжительностью...насколько я помню было одно длительностью 30 минут конструктор копирования! Когда будешь записывать видео ответы на ваши вопросы озвучь, пожалуйста, с помощью какой программы монтируешь видео! Случайно не Sony Vegas Pro 13? ))))
Пожалуйста! Монтирую с помощью Vegas Pro 14
выдает ошибку error: declaration of template parameter 'T' shadows template parameter|
Потому что Node не должен быть шаблоном, если List - шаблон. Или, по крайней мере, имя шаблонного параметра у Node не должно совпадать с таковым у List. Но лучше все-таки первый вариант.
Вопрос: как сохраняется указатель *current, который создался в методе push_back? Разве он не должен уничтожится когда мы выходим за область видимости?
20:42 Для тех кто решил запустить код на этом этапе и компилятор выдал ошибку: Нужно прописать деструктор класса List, хотя бы пустой.
Господи, чувак, спасибо большое! Деструктор у меня был, но похоже кривой, но заработало!
спасибо
Спасибо.
КРАСАВА
Серьезность Код Описание Проект Файл Строка Состояние подавления
Ошибка C2440 =: невозможно преобразовать "List::Node" в "List::Node *"
with
[
T=int
]
та же ерунда
В классе List в конструкторе Node в скобках напиши так: Node(T data=T(), Node* pNext = nullptr)
head = head->pNext;//head получает адрес следующего элемента списка
Но где в коде описано когда этот адрес на следующий элемент получен? Когда head->pNext получило какое-то значение, а не nullptr?
Если мы динамически выделяем здесь память, почему нет ее освобождения?
Я правильно понимаю, что pop_back невозможно сделать за O(1), так как даже, если у нас есть указатель на послед. элемент, то, имея односвязный список: []->[]->[]->nullptr , чтобы удалить последний нужно предпоследнему сделать nullptr, иначе будет висячий указатель(последний же удалится). Предпоследний же нужно также перебирать сначала списка.
Знаю вопрос глупый, но! Не могли бы вы объяснить почему мы не можем класс Node вписать вне класса List и потом просто к нему обращаться
8:20 не понял зачем это нужно? если мы передадим класс или любой другой тип данных,
то у нас в любом случае переменная data будет инициализирована, так как в конструкторе this->data = data;
Но вы сами сказали на 7:59 , что данных нет. в T будет храниться мусор.
Это великая работа) Спасибо за урок, ради такого видео даже ляма лайков не жалко! Сергей, а почему многие ютуберы, те же самые форумы говорят, что ООП не нужно? Я не понимаю такой логики, тоже самое говорят про Java, ведь с++ основан на добавлении ОПП в язык Си?
Большинство топовых языков программирования объектно ориентированные, в большинстве вакансий требуется знание принципов ООП. ООП удобно, понятно и громадное количество ПО написано с применением ООП, а этот код нужно поддерживать. Это так на вскидку. Так что ООП востребовано и будет востребовано ещё очень долго. Я не отношусь к противникам или последователям ООП или процедурного стиля, а принимаю это просто как инструменты которые могут быть удобны в той или иной ситуации. Всякие радикальные точки зрения считаю не соответствующими реальности фантазиями.
Спасибо за совет, но просто обратил внимание и стало интересно, вот решил разузнать у опытного программиста=)
Хороший ответ, почитав ваш комментарий я понял, что не только опытные программисты сидят на форумах, а ещё мамкины программисты. Я задал этот вопрос не потому что я пытаюсь как укоротить своё изучение, а для получения важной информации от вас, как от опытного программиста=) Благодарю за ответ, ваши видосики постоянно репостю(хз как это пишется=)))), дабы помочь вам и вашему хорошему каналу)
Так вот почему делают итераторы - в частности, чтобы при последовательном выводе элементов списка (например, на печать) не искать элементы для каждого индекса заново и получить при этом O(n) вместо O(n^2).
И, кстати, push_back() в ролике сделан со сложностью O(n) из-за того, что нет указателя на хвост head.
Ребята, подскажите пожалуйста, каким образом новый экземляр класса Node присваивается укателю header в области видимости метода pushback 16:30 строка 60 (Node* header = new Node(data)). Как это работает? Обычно к указателям можно присвоить ссылки.
А меня одного беспокоит, что к примеру в этом моменте: "head = new Cell(data);" или в этом "current->pNext = new Cell(data);" динамическая память выделяется, но не освобождается, и мы все равно компилируем проект?
Я конечно мог что-то упустить или не понять, но все же
Окей, а что там с деструктором?
(16:15) - здесь ошибка. if (head = nullptr) -это не сравнение, это присвоение
:))) ок, понял, тороплю события (17:40)
лучший!
спасибо.
А если через оператор индексирования нужно вывести несколько элементов, как это сделать?
Сложно, но понять можно!
Всё бы хорошо, но в списке добавление элемента происходит за константное время, в этом весь смысл списка. У вас же добавление за сделано за O(n)
браво
Не видит шаблон template. Ошибка Declaration of 'T' shadows template parameter. Mac OS X 10.13.4 , cреда разработки XCode 9.3.
Почему не видит, пока не пойму. Кто встречался с проблемой подскажите как решить. Cпасибо заранее.
Мне помогло просто удалить строку template над объявлением класса Node. Класс List является шаблонным, так что класс Node не нужно делать шаблонным он и так может работать с типом Т, т. к. является частью класса List. Так как в видео возможно только с visual studio.
@@masasikisimoto26 У меня в VS 2017 (на 32-разрядной W7) в строчке под название этого шаблона подчеркивалось красным пунктиром слово List перед круглыми скобками - в выражении List::List(). Ничего из прочитанного в этом форуме не помогало. Тогда я просто воспользовался подсказкой с желтой лампочкой, которая возникала при подведении курсора к месту ошибки: там было написано что-то вроде "Создать определение List в файле source.cpp". Я согласился, закрыл открывшуюся после этого форму ввода данных, никаких добавлений к коду не обнаружил, но подчеркивание исчезло. Затем вместе с Сергеем прошел отладку (с 16:57). Вроде, все нормально пока...
@@pruss_utb184 может ты просто забыл объявить конструктор List() внутри самого класса, в public секции. Или возможно просто забыл где ; поставить или скобку пропустил.
@@masasikisimoto26 Верно: после упомянутой выше отладки, эта проблема все равно давала о себе знать и я в конце концов создал конструктор (а заодно - и деструктор) по умолчанию в public секции класса List. Дальше все работало нормально до самого конца.
Такая же дичь , как решал ?