лекции (2008) (by Михайлишин Алексей_ Жбанков Денис_ Щербинин Виктор_ Чеботарев Павел), страница 4
Описание файла
PDF-файл из архива "лекции (2008) (by Михайлишин Алексей_ Жбанков Денис_ Щербинин Виктор_ Чеботарев Павел)", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 4 страницы из PDF
}Также считается, что 0 может преобразовываться к любому перечислимому ТД.В языке C перечислимый ТД реализован неэффективно.enum C {c1,c2,c3}; // c1=0, c2=1, c3=2x = c1;x = -25; //не ошибка!Можно так же описать константы:const int c1=0; //и т.п. ...#define c1 0Таким образом, программистам вовсе не обязательно было использовать перечислимый ТД.
В C++ сделанследующий шаг в усовершенствовании перечислимых ТД. В нем можно управлять нумерацией перечисленийПример:enum Mode{Read = 0x1,Write = 0x2,ReadWrite = Read|Write}Недостатки: пониженная надежность.В C# не существует возможности преобразования между enum и int.Атрибутирование - частный случай рефлексии(отражение информации об исходных текстах в бинарныхкодах), приписывание некоторому ТД атрибута.Мы рассмотрим атрибут flags. Если установлен этот атрибут, то над ТД можно выполнять бинарныелогические операции.Т.о.
перечислимый тип в C# получился достаточно мощным и активно используется. Enum, struct, простыеТД - в C# называются value types. Для каждого из таких типов существует "коробка" (box). Каждомупримитивному ТД соответствует специальный класс-обертка (Wrapper Class). Например, для int - Int32, дляuint - UInt32. Все эти типы наследуются от Object. У каждого класса, наследованного от Object, есть методtoString().Для перечислимых ТД существует класс System_Enum.Пример на Java:enum Color {Red,Green,Blue}Color c;c = Color.Red;В Java потеряна вся связь между enum и целыми числами. Любое перечисление - наследник класса Enum.enum RGBColor {public RGBColor(byte R, byte G, byte B)private int color;}Red(255,0,0)Green(0,255,0)Blue(0,0,255)Таким образом, все перечислимые типы превратились в классы, поэтому все претензии к ним от Виртаисчезают.[lect10] VI) Ссылки и указателиЯзыки делятся на два класса с точки зрения указателей: строгие и нестрогие.
Вопрос: можно ли описать вязыке Паскаль указатель на integer? Ответ: нет.••Строгие языки – указатели могут в них использоваться только для адресации анонимных объектовв динамической памяти. К ним относятся Ада, Оберон, Модула-2, Паскаль, Ада-83. В них нельзясмешать статические объекты и динамические объекты.Нестрогие языки – в них, кроме того, что есть в строгих языках, есть еще адресная арифметика иможно получить адрес любого объекта. Примеры: С, С++, Delphi.
Проблемы: например,возвращение функциями указателей на локальные объекты.Ада:type PT is access T;Модула-2:TYPE PT = POINTER TO T;Описание указателя на необъявленный тип (Ада):type PT is access;type T is recordnext: PTend recordtype PT is access T....x:PTx:= new T;В строгих языках над указателями допустимы только операции присваивания и разыменования.М-2:x^.nextОберон:x.next //как обращение к св-ву объектаЕще один пример ошибки в нестрогих языках:static int i;...int *p;p=&i;free(p);// - ошибка!!При отладке такие ошибки можно находить, используя «отладочный» менеджер памяти. Как избежатьпроблемы нестрогих языков? Использовать строгие языки.
Но этим все проблемы не решаются, если в языкеесть явная операция освобождения памяти.Проблемы, возникающие из-за явного освобождения памяти:1) Мусор.T* x=new T();T *x1=new T();x=x1;// появление мусораОшибка в программе – любое несоответствие требованиям пользователя. Мусор – серьезнаяпроблема в промышленном ПО.2) Висячие ссылки – использование адреса несуществующего объекта.T* x=new T();T* x=x1;x1=x;delete x; //появление висячей ссылки x1Решение этих проблем – автоматическая сборка мусора. Способы сборки мусора:1) Подсчет ссылок. Каждый выделенный кусок памяти помечается счетчиком. При выходе из областивидимости счетчик уменьшается на 1. Когда счетчик=0 – объект уничтожается.2) Учет памяти (mark&scan). В некоторые моменты времени запускается сборщик мусора, помечающийиспользуемые куски, сдвигающий их к началу кучи и освобождающий неиспользуемые куски.
Приэтом значения указателей и ссылок меняется, и сборщик мусора исправляет эти значения впрограмме.Языки с автоматической сборкой мусора не используются в realtime-системах, т.к. они при некоторыхусловиях (при нехватке памяти) сильно тормозят выполнение программы.В стандарте языка Ада не используется автоматическая сборка мусора (т.к. одним из основных егоприоритетов является эффективность), но в реализациях ее компиляторов она может быть.
Компилятор, нереализующий сборку мусора, обязан реализовать DEALLOCATE(p). Модула-2: в этом языке также нетавтоматической сборки мусора, есть спец. модуль ALLOCATOR, в котором есть две процедуры – ALLOCATE иDEALLOCATE, спец. тип данных ADDRESS – к нему может быть неявно приведен любой указатель.Такие типы данных (ADDRESS, void *) использовались программистами в основном при созданииуниверсальных контейнеров. Так понятие адреса проникло в строгие языки.
Только Оберон остался«чистым» от этого понятия. В нем автоматическая сборка мусора.C#, Java – в них вообще отсутствует понятие указателя. Value types в этих языках называются простыетипы и некоторые структуры (известного размера), для них отводится память под них самих. Для всехостальных объектов («большие» объекты – массивы и объекты большинства классов) память отводится дляссылки, а сами объекты располагаются в динамической памяти и являются анонимными. Этот принципназывается преференциальная модель объекта.var X:T; {если T – имя класса, то X - ссылка}Ада83 – строгий язык. В нем автоматическая сборка. В нем есть атрибут A’BASE – адрес объекта, но встандарте говорится, что программы с его использованием непереносимы.
Ада95 – появление атрибутаa’access – адрес a. До Ады95 в ЯП Ада нельзя было применять концепцию объектов. Ко времени созданияАды95 изменились технологические предпосылки для этого языка. К этому времени было очевидно, что Адане будет универсальным языком. В Аде95 можно передавать адрес, но только структур. Этот язык осталсянадёжным. a’access выдает адрес. Но для статических объектов адрес брать нельзя:A: X;A’ACCESS; - ошибка.i: aliased integer; //aliased указывает, что к i применима адресная операция.TYPE PT IS ACCESS T; //PT можно использовать только для динамических объектов.TYPE PI IS ACCESS ALL INTEGER; //PI может использоваться как для объектов издинамической памяти, так и для ALIASED.В Java есть JNI – Java Native Interface – возможность вызывать родные системные вызовы данной системы –противоречие WORA (Write Once, Run Anywhere), но это повышает производительность.В C# оставлена «дырка» - спецификатор unsafe {} , в блоке которого можно использовать указатели.fixed(byte *p=new byte(10)){...} – эта конструкция указывает, что соотв.
ссылка не может меняться впроцессе сборки мусора. Аналогично - в visual studio c++ есть тип CString – надежная динамическая строка,этот тип появился до STL. В этом типе есть указатель на char *, и его можно получить, но этот классиспользует алгоритмы, подобные алгоритмам сборки мусора, и этот указатель может измениться. ВызовS.GerBuffer() запрещает изменения этого адреса, но после использования нужно вызвать S.ReleaseBuffer(),чтобы опять разрешить изменения.Все объекты C#, Java, Delphi являются ссылками.C#, Java:X a = new X(); //единственный способ порождения объектаDelphi:a: X;a := X.create; {в этот момент отводится память и вызывается конструктор}a.
– разыменовывание ссылки.В С++ ссылка – синоним объекта, аналог другого имени. К ссылке в С++ применима единственнаяоперация – инициализации.T b;T &a = b; //а – синоним bint x;int &i;x = 0;i = 1;cout << x; //будет выведено 1Одному объекту соответствует 2 имени – может получиться путаница.Где применяется:•••X &a = GetSomeObject(); //вместо того, чтобы постоянно вызывать GetSomeObject()Параметры функций или возвращаемое значение.Член класса – инициализируется в списке инициализации конструктора.Мы закончили рассмотрение примитивных типов данных в традиционных ЯП.Зачем Страуструп ввел ссылочный тип? Для того, чтобы можно было переопределять стандартныеоперации.
Например, при переопределении операций = , [] лучше использовать ссылку, а не указатель. Вомногих библиотеках есть спец. типы – разумные указатели – классы, в которых переопределена операция >. Подробнее в книге Андрея Александреску, «Современное проектирование на С++: Обобщенноепрограммирование и прикладные шаблоны проектирования».[lect12] Глава 2. Составные ТДI) Классификация СТД• массивы• записи/структуры -> классы• множества• файлы• строки• ассоциативные массивы (хеш-таблицы)Все типы, кроме массивов и структур, не имеют четко определенных эффективных алгоритмов управления иметодов хранения.
Например, сортировать ассоциативный массив можно с помощью qsort, heapsort,пирамидальной сортировки, каждая из которых имеет недостатки на определенных наборах ключей.Поэтому встраивать фиксированные методы в компилятор не всегда оптимально.II) Массивыпоследовательность однотипных элементов (непрерывная, с точки зрения размещения по памяти)Атрибуты массива:• базовый тип => D• тип индексов (для этого типа должны быть применимы операции succ и pred, основаны на целых)• L..R (левая и правая граница)и связанный с ним атрибут LengthСвязывание массива с типом его элементов статическое во всех языках (т.е. на этапе компиляции).Именно для решения этой проблемы ввели void* (ADDRESS) для указания абстрактного адреса на объект.При реализации массивов (да и любых вещей) надо находить компромисс между:• надежность• эффективность• гибкость (удобство для программиста)/про сравнение гибкости, надежности и т.д.
для разных языков; си – эффективен, например (нумерациямассивов всегда идет с нуля, а вот в Паскале может быть как угодно)/Операции, применимые к массиву:• индексация (от двух аргументов: массив и индекс) – возвращает ссылку на элементD: [], A,i => ref D• изменение атрибутов (например, размера)Существуют открытые массивы (например, в Modula2) – это, по сути, шаблон:procedure P(var A:T); //здесь T – открытый массив, формальный параметр функцийA: ARRAY OF TВызывая, HIGH(A) мы получаем правую границу, левая граница – 1.