Vapaamies писал(а):На самом деле тут скорей будет похоже на повторение функциональности GetMem, только размазанной по объектам. И накладные расходы тоже размазанные. Менеджер кучи ведь тоже хранит много служебной инфы, поэтому еще неизвестно, где расход памяти будет больше. У GetMem расходы на каждый экземпляр, а не на класс в целом.
Во-первых, если вы собираетесь "раздвигать" поля данных в объекте, то ни о каком размещении на стеке или в коллекциях речи уже не идёт. Всё равно придётся разещать их на куче.
Во-вторых, операция realloc, то есть перевыделение памяти большего объёма, требует больше времени и ресурсов, чем обычная GetMem, поскольку далеко не факт, что можно увеличить имеющийся блок памяти сзади, поскольку там уже могут быть другие данные. На практике выделяется новый блок памяти большего размера, после чего туда копируются данные из старого блока памяти. И, что самое главное, в итоге вы получаете
новый указатель на область данных. Так что если вы уже наплодили ссылок на ваш объект, то вам либо придётся их все скорректировать, либо городть особую структуру для обращения к объекту, когда реальный указатель хранится в специальной структуре связи, а все ссылки ведут на эту структуру. Тогда да, тогда можно менять указаетль на область памяти "на лету", но в этом случае накладные расходы, опять же, возрастают, поскольку нужно будет считывать два указателя, а не один, причём при каждом обращении к объекту через указатель.
Что касается менеджера кучи, то я ещё раз вам повторяю, что обращение к менеджеру кучи происходит во много раз реже, чем к полям данных объекта. У нас в проектах полей данных в объектах по нескольку десятков, так что тут даже никаких особых статистических исследований проводить не требуется.
Будут ли вложенные поля создавать дополнительную нагрузку на процессор и/или его кэш, нужно еще обдумать. Чисто по прикидкам, обращение к объектным полям в обязательном порядке требует Self в регистре, куда он кладется из тела владельца, так что обращение к памяти задействуется и блок с куском объекта в кэш попадает, и промах вряд ли случится... Нужно еще обдумать и код примерный написать.
Сейчас, когда вы обращаетесь к объекту, вы в любом случае считываете указатель на этот объект. Соответсвтенно, во все вызовы, где требуется Self, будет складываться он же. То есть, никаких ополнительных обращений к памяти не потребуется.
В предлагаемом вами механизме, прежде чем получить доступ к полю данных в объекте Detail1, вы дожны будете в начале считать смещение к его области данных из объекта Main, чтобы узнать откуда начинается таблица полей объекта Detail1. Потом считать смещеие к полю данных Detail1 из его таблицы смещений, и только после этого вы сможете определить адрес поля данных и осуществить к нему доступ. Итого, две дополнительные операции чтения данных и три сложения для вычисления адреса.
Кстати, мысль "написать примерный код" весьма здравая, попробуйте, а потом будем спорить.
Vapaamies писал(а):Гм, гм... а если взять код любой процедуры SaveToFile, ее авторы тоже не умеют писать программы? Подобный код встречается довольно часто, так что аргумент о частых обращениях к полям нужно подкреплять статистикой.
Я так понимаю, что вы имели в виду код процедуры LoadFromFile? Да, подобный код будет практчиески в каждом объекте в большой и сложной прикладной системе, поскольку нам нужно сохранять и загружать данные, с которыми мы работаем, иначе нет смысла в наших программах. Но вы явно путаете наличие кода и частоту его использования в программе. Постоянное чтение и запись данных будет происходить только в каких-либо конверторах данных, которые преобразуют файлы одного формата в другой. В остальных прикладных программах соотношение времени загрузки данных к остальной обработке не более 5%, а во многих расчётных программах или программах моделирования, где данные загружаются сравнительно редко, может быть и менее 1%. У нас вон архитекторы при работе могут утром файл один раз открыть и целый день с ним работать.