Вопросы по С/С++ (СИ)
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Шаблон тут не спасёт. Шаблон - это, как бы Вам проще объяснить, некая заготовка, не имеющая конкретного типа данных. Он (тип) определяется с объявлением объекта по этому шаблону.
Вопрос по Вашему сабжу. А что Вам мешает, удалив необходиый Node из списка, удалить данные, связанные с ним ? Ссылку то на данные имеете.
Вопрос по Вашему сабжу. А что Вам мешает, удалив необходиый Node из списка, удалить данные, связанные с ним ? Ссылку то на данные имеете.
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Alex
Просто хотел подчистить код, в котором применяется класс QLIST.
Типа, чтобы строкой
удалялись из памяти все ноды и данные с ними связанные.
Проблема в том, что под void указателем может скрываться что угодно.
А этот класс используется для формирования списков данных различного типа.
Только с условием: один список - один тип данных для всех нодов данного списка.
А на данный момент это выглядит так:
где childList является объектом класса QLIST.
Это деструктор класса Widget. При удалении виджета, удаляются все его дочерние виджеты.
После выхода из деструктора виджета вызывается деструктор объекта childList автоматически.
Хотя наверное это неправильно и в конструкторе класса Widget надо бы создать объект childList оператором new
и в деструкторе виджета удалить вручную childList оператором delete. Или не стоит заморачиваться?
Но по крайней мере, трассировка кучи не обнаруживает утечек памяти.
Просто хотел подчистить код, в котором применяется класс QLIST.
Типа, чтобы строкой
Код: Выделить всё
delete childList;
удалялись из памяти все ноды и данные с ними связанные.
Проблема в том, что под void указателем может скрываться что угодно.
А этот класс используется для формирования списков данных различного типа.
Только с условием: один список - один тип данных для всех нодов данного списка.
А на данный момент это выглядит так:
Код: Выделить всё
Widget::~Widget()
{
Widget *pC = 0;
childsList.pointer_begin();
while(childsList.get_data_next((void**)&pC) == true)
{
delete pC;
}
}
где childList является объектом класса QLIST.
Это деструктор класса Widget. При удалении виджета, удаляются все его дочерние виджеты.
После выхода из деструктора виджета вызывается деструктор объекта childList автоматически.
Хотя наверное это неправильно и в конструкторе класса Widget надо бы создать объект childList оператором new
и в деструкторе виджета удалить вручную childList оператором delete. Или не стоит заморачиваться?
Но по крайней мере, трассировка кучи не обнаруживает утечек памяти.
I am DX168B and this is my favourite forum on internet!
Re: Вопросы по С/С++ (СИ)
Плюсы-же - пусть объект сам о себе заботится:
Конструктор не обязателен - но инициализация лишней не бывает - а то позабытый случайно на стеке объект бабахнет на мусорном адресе при неявной деструкции.
DX168B писал(а):Код: Выделить всё
typedef struct _tag_Node
{
_tag_Node() : nodeId(-1), next(NULL), prev(NULL), ptr(NULL) { }
~_tag_Node() { delete ptr; }
long int nodeId;
Node *next;
Node *prev;
void *ptr;
} Node, *pNode;
Конструктор не обязателен - но инициализация лишней не бывает - а то позабытый случайно на стеке объект бабахнет на мусорном адресе при неявной деструкции.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! 
Re: Вопросы по С/С++ (СИ)
DX168B писал(а):Проблема в том, что под void указателем может скрываться что угодно.
Заведите базовый объект для всех используемых типов - а потом вдарьте по ним полиморфизмом!
DX168B писал(а):Только с условием: один список - один тип данных для всех нодов данного списка.
Либо взять уже готовый стандартный std::list либо изобрести такой-же my_list вручную.
DX168B писал(а):После выхода из деструктора виджета вызывается деструктор объекта childList автоматически.
Хотя наверное это неправильно и в конструкторе класса Widget надо бы создать объект childList оператором new.
Я бы сказал деструктор объекта childList вызывается неявно [как и для всех не-динамических полей класса] в ходе исполнения деструктора самого класса. И да, никакой неправильности в его не-динамичности нет - место будет выделено в области данных самого объекта класса - т.е. вместо двух объектов в куче (класс и список) вы поимеете один объект. Когда жизнь заставит разобираться с операторами присвоения объектов класса - динамические поля тоже потребуют к себе несколько завышенного внимания, чтобы впредь стараться обходиться без них.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! 
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Конструктор не обязателен - но инициализация лишней не бывает - а то позабытый случайно на стеке объект бабахнет на мусорном адресе при неявной деструкции.
Я в курсе. Поля структуры у меня все равно заполняются сразу же после создания.
Создаются они у меня в методах ::add(), ::insert() и в ::add_sort()
Вне класса я ничего со структурой не делаю. Все происходит внутри класса QLIST. Как рождение так и смерть этих структур.
Потому я и не заморачивался с конструкторами в структуре.
В конструкторе класса Widget, к примеру, вся инициализация есть.
Код: Выделить всё
//////////////////////////////////////////////////////////////////
// GUI wiget base class (inherited from GuiObject)
Widget::Widget()
{
drawContext.xPos = 0;
drawContext.yPos = 0;
drawContext.zPos = 0;
drawContext.xSize = 0;
drawContext.ySize = 0;
drawContext.zSize = 0;
drawContext.objectID = 0;
drawContext.extContext = 0;
drawContext.extContextType = DRAW_EXTENDED_CONTEXT_TYPE_NONE;
enableFlag = true;
focusFlag = true;
renderFunc = 0;
eventCallBack = 0;
}
Передачу параметров в конструктор не делал. Все реализовано отдельными методами, так как
виджетами рулят внешние скрипты. Конечно, можно все инициализации структуры drawContext вынести в конструктор структуры,
что было бы правильнее, так как над ней проводятся операции и вне класса Widget. Так и сделаю. Спасибо за наводку.
Заведите базовый объект для всех используемых типов - а потом вдарьте по ним полиморфизмом!
Подумываю над этим. Что-то придется переделать.
Я просто поинтересовался, можно ли сделать это более изящно, чем то, что у меня сейчас есть.
Либо взять уже готовый стандартный std::list либо изобрести такой-же my_list вручную.
Ну, свой лист я создавал не просто так. Дело в том, что по этому списку производится рендеринг, по нему же идет перебор
при передачи событий объектам. Рендеринг объектов должен производиться в особом порядке из-за особенностей OpenGL.
И этот порядок динамически изменяется под действием кучи параметров.
А std::list у меня уже используется в других местах.
Я бы сказал деструктор объекта childList вызывается неявно [как и для всех не-динамических полей класса] в ходе исполнения деструктора самого класса. И да, никакой неправильности в его не-динамичности нет - место будет выделено в области данных самого объекта класса - т.е. вместо двух объектов в куче (класс и список) вы поимеете один объект. Когда жизнь заставит разобираться с операторами присвоения объектов класса - динамические поля тоже потребуют к себе несколько завышенного внимания, чтобы впредь стараться обходиться без них.
Да уж стараюсь поменьше плодить динамических сущностей. Ибо это бьет как по надежности, так и по производительности.
И после дебага всегда проверяю логи по утечкам. Собственно, у меня и был вопрос по механизмам освобождения памяти.
Просто небыло понятно про неявный вызов деструктора childList. Это типа стандарт, или особенность одного компилятора?
Просто сейчас это пишется в Visual Studio 2010, потом будет переезжать на GCC, когда будет портироваться под Linux.
Код: Выделить всё
~_tag_Node() { delete ptr; } А корректно ли поведет себя оператор delete в этом случае?
Просто удаление объектов происходит одним способом, а удаление, допустим, строк (массивов) другим способом.
Ну, типа void может ссылаться как объект класса так и на обычную строку. А этот самопальный класс у меня используется и для списков строк, а в некоторых случаях и для отдельной строки. По символу на ноду. Просто в OpenGL рендеринг динамического текста - тот еще секас.
I am DX168B and this is my favourite forum on internet!
Re: Вопросы по С/С++ (СИ)
DX168B писал(а):Рендеринг объектов должен производиться в особом порядке из-за особенностей OpenGL.
И этот порядок динамически изменяется под действием кучи параметров.
Ну т.е. он ещё и сортируется время от времени? В STL, кстати, алгоритмы есть разные - в т.ч. с заданием критериев обработки. Пока непонятно в чем преимущество самопального списка.
DX168B писал(а):Просто небыло понятно про неявный вызов деструктора childList. Это типа стандарт, или особенность одного компилятора?
Просто сейчас это пишется в Visual Studio 2010, потом будет переезжать на GCC, когда будет портироваться под Linux.
Вызов деструктора для не-динамических объектов - обязанность компилятора, либо по выходу из блока в котором он был объявлен, либо по уничтожению объекта-владельца как в описываемом случае.
DX168B писал(а):Код: Выделить всё
~_tag_Node() { delete ptr; }
А корректно ли поведет себя оператор delete в этом случае?
Просто удаление объектов происходит одним способом, а удаление, допустим, строк (массивов) другим способом.
В данном случае никакой информации об объекте нету - и даже если скомпилирует без предупреждений-ошибок - всё, скорее всего сведётся к вызову free для освобождения указуемого блока памяти. Если же указывается объект - то будет исполнен его деструктор - даже если тип этого указателя - абстрактный базовый. Для удаления массивов выделенных посредством new[] хорошо не забывать использовать delete[] - ибо деструкторы всех элементов жаждут исполнения. А для строк есть std::string.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! 
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Пока непонятно в чем преимущество самопального списка.![]()
Минимализм. Пробовал различные варианты. При большом количестве объектов жутко проседает FPS.
Это еще сильнее проявится, когда этот код заработает на Paspberry Pi.
Самопалом я добился нужного функционала за существенно меньшее количество операций.
Это просто узкое место в программе и тут производительность играет большую роль.
I am DX168B and this is my favourite forum on internet!
-
Pnjom-Penb
- Мучитель микросхем
- Сообщения: 469
- Зарегистрирован: Вс авг 30, 2015 03:52:59
Re: Вопросы по С/С++ (СИ)
Про использование иерархии классов для хранения разных наборов данных уже говорили выше, а чтобы корректно отрабатывал delete, нужно объявить деструктор базового класса виртуальным. В этом случае деструктор базового класса автоматически вызывается после деструктора производного класса.DX168B писал(а):А корректно ли поведет себя оператор delete в этом случае?
Re: Вопросы по С/С++ (СИ)
DX168B писал(а):Пробовал различные варианты. При большом количестве объектов жутко проседает FPS.
Угу, ПМСМ, std::list из указателей на объекты столь-же "удобен" в использовании как и имеющаяся C-style реализация, а не-динамические объекты в нём держать - на копированиях разориться можно. Попробуйте свою реализацию ошаблонить, используя в качестве параметра тип хранимого объекта - разницы в производительности не будет, ну разве что программу кратно числу разных типов параметров шаблона раздует слегка. А позднее связывание на скорости скажется в худшую сторону.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! 
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Siarzhuk
Вот как раз ошаблонить этот класс я и собирался. А то, что его "раздует" на количество применяемых типов - так это некритично.
Правда, с шаблонами разбираться придется.
Вот как раз ошаблонить этот класс я и собирался. А то, что его "раздует" на количество применяемых типов - так это некритично.
Правда, с шаблонами разбираться придется.
I am DX168B and this is my favourite forum on internet!
Re: Вопросы по С/С++ (СИ)
DX168B писал(а):Правда, с шаблонами разбираться придется.
Сделайте копию QLIST, работающую с одним из типов объектов, минимизируйте интерфейс либо поместив функции обработчики QLIST в отдельный модуль либо сделав их членами класса QLIST, а как всё соберётся и заработает - на основе этого модуля/класса сделайте шаблон и окончательно используйте его для других типов.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! 
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Там всё просто.DX168B писал(а):Правда, с шаблонами разбираться придется.
Шаблон позволяет определять тип данных, используемых в объекте, во время объявления этого объекта.
Например:
Код: Выделить всё
struct Node{
...
...
type_data Data;
};
В таком случае, создаёте шаблон, типа :
Код: Выделить всё
template <typename type_data> struct Node{
...
...
type_data Data;
};
Например :
Код: Выделить всё
Node <int> node;
Шаблон огораживает создание вручную кучу одинаковых экземпляров с разными типами, создавая автоматически отдельный экземпляр со своим типом, при объявлении объекта.
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Alex
ОК. Понял. Разберусь. Ошаблонивать придется и класс QLIST, чтобы выбросить из него void указатели. (некоторые методы имеют в принимаемых аргументах аналогичные указатели) Тогда я смогу смело
сносить привязанные данные в деструкторе класса QLIST, а за тем и сами ноды.
Более того, данные я смогу сносить прямо в деструкторе удаляемой ноды, таким макаром:
и оператор delete отработает нормально, так как тип определен шаблоном при инициализации.
То что надо. Спасибо за подсказки.
ОК. Понял. Разберусь. Ошаблонивать придется и класс QLIST, чтобы выбросить из него void указатели. (некоторые методы имеют в принимаемых аргументах аналогичные указатели) Тогда я смогу смело
сносить привязанные данные в деструкторе класса QLIST, а за тем и сами ноды.
Более того, данные я смогу сносить прямо в деструкторе удаляемой ноды, таким макаром:
Код: Выделить всё
~_tag_Node() { delete ptr; } и оператор delete отработает нормально, так как тип определен шаблоном при инициализации.
То что надо. Спасибо за подсказки.
I am DX168B and this is my favourite forum on internet!
Re: Вопросы по С/С++ (СИ)
Здоровья всем! Вопрос по С.
Есть массив arr, забитый из ЕЕПРОМа и переменная tot.
Эта переменная может иметь разные изменяемые значения от 2 до длины массива (16).
Подскажите, как более-менее равномерно распределить данные из этого массива, например в другой массив размером с tot? Понятно, когда 16 кратно значению tot. А в других случаях? И желательно по минимуму затрагивать arr[0].
Есть массив arr, забитый из ЕЕПРОМа и переменная tot.
Код: Выделить всё
uint_fast8_t arr[16]={0,45,8,120,18,24,32,64,90,126,147,168,200,255,33,56};
uint_fast8_t tot;Подскажите, как более-менее равномерно распределить данные из этого массива, например в другой массив размером с tot? Понятно, когда 16 кратно значению tot. А в других случаях? И желательно по минимуму затрагивать arr[0].
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Какие то мысли вслух, а не вопрос. Ничего не понятно...
Re: Вопросы по С/С++ (СИ)
Аlex, прошу прощения.
К примеру, если tot==8, то из массива arr выбирается каждая вторая запись и копируется в другой массив, размерностью = 8 байт.
Если tot==4, то из массива arr выбирается каждая четвертая запись и копируется в другой массив, размерностью = 4 байт. Т.о. выборки из массива arr распределятся по всей его длине. И вопрос: как это дело(распределение выборок) поумнее схимичить, если tot получился, к примеру = 7 или там 11...?
К примеру, если tot==8, то из массива arr выбирается каждая вторая запись и копируется в другой массив, размерностью = 8 байт.
Если tot==4, то из массива arr выбирается каждая четвертая запись и копируется в другой массив, размерностью = 4 байт. Т.о. выборки из массива arr распределятся по всей его длине. И вопрос: как это дело(распределение выборок) поумнее схимичить, если tot получился, к примеру = 7 или там 11...?
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Ну, в случае с 4 или 8, то тут понятно - делим просто на это число и всё.
А вот с "нестандартными" значениями - тут, как бы, и нам не понятно, что Вы хотите.
А вот с "нестандартными" значениями - тут, как бы, и нам не понятно, что Вы хотите.
Re: Вопросы по С/С++ (СИ)
Ну плин...
Аlex троллите что ли? Фуф. Попробую "на пальцах". Есть у Вас веревка/нитка... длиной = размерности(длине) массива arr. То бишь 16 условных метров. Нужно сложить ее в tot максимально одинаковых кусков. Значение tot может быть разным от 2 до 16. Так понятнее?
Вот как раскидать tot выборок по массиву, по возможности равномерно? С флоатом связываться не хочется, для 2 килобайт флеша это жирновато будет.
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Не, не трлллю, честно 
Просто мне действительно не понятно, как выбирать значения, если, например, будет число 9.
Просто, для примера, назовите выборки для tot = 9.
Просто мне действительно не понятно, как выбирать значения, если, например, будет число 9.
Просто, для примера, назовите выборки для tot = 9.
Re: Вопросы по С/С++ (СИ)
Так и мне непонятно, оттого и спросил.))
Воот. Получается, в основном, выборка будет через одну ячейку массива(0,2,4...), а где-то указатель должен попасть и на следующую, за выбранной, ячейку. Что-то типа: 1,3,5,7,9,10,12,14,15. (Нулевую ячейку, по возможности, не трогать). Вот как схимичить эту автоматику?для примера, назовите выборки для tot = 9