Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
23-25.docx
Скачиваний:
11
Добавлен:
05.05.2019
Размер:
68.05 Кб
Скачать
  1. Классификация покрытий:

Покрытие – это эквивалентные множества ФЗ. При этом, под эквивалентным множеством понимают такие множества F1 и F2 на схеме R, когда они взаимообратные, т.е., из множества F1 путем применения аксиом вывода, может быть получено F2, а из множества F2, аналогичным способом, может быть получено обратное множество F1.

Различают следующие покрытия:

  1. Неизбыточное – покрытие, которое не содержит избыточных ФЗ. У каждого множества ФЗ может быть несколько неизбыточных покрытий. Вид неизбыточного покрытия во многом определяется порядком, в котором ФЗ проверяются на избыточность. F={AB, AC, ABC}. Получаем не избыточные покрытия: F1={AB, AC} или F2={ABC}.

  2. Минимальное – неизбыточное покрытие, содержащее наименьшее количество ФЗ. Их так же может быть несколько. Если рассматривать ФЗ F1 и F2 - они оба не избыточные, но минимальным среди них является только F2. На нем осуществляют декомпозицию.

  3. Редуцированное – множество, содержащее в себе только редуцированные ФЗ. ФЗ называется редуцированной, если она слева и справа не содержит посторонних атрибутов. Н-р, F3={AB, ABC}. ФЗ ABC, содержит лишний атрибут в левой части – B. Т.о., покрытие F4={AB, AC} – является редуцированным, но не минимальным.

  4. Каноническое – неизбыточное покрытие, состоящее из полной ФЗ, правая часть которой содержит только один атрибут. Канонические покрытия выполняют вспомогательную роль, при получении минимального покрытия и неизбыточного. Декомпозицию на таком покрытии не производят..

  5. Оптимальное – покрытие, для которого не существует эквивалентного ему множества с еще меньшим числом вхождений атрибутных символов.

F7 = {ABCD, ABE, EAB}. (10 симв);

Оптимальное: F8 = { ECD, ABE, EAB} (9 симв)

  1. Кольцевое – используется в качестве основания для декомпозиции на минимальном покрытии ФЗ с эквивалентными левыми частями. Множество ФЗ называется кольцевым покрытием множества F, если оно эквивалентно ему и представлено виде комплексных ФЗ. Например, для множества F9 = {AB, BA, BC, CD} кольцевое покрытие будет иметь вид: G1 = {(A; B) C; (C) D}. Кольцевые покрытия могут быть: неизбыточными, минимальными, редуцированными, оптимальными.

F= {A->BDC, B->ACE}. G={(B)->ACE, (A)->BCD} - неизб, G={(B)->AE, (A)->BCD} - редуцир,

G={(B, A)-> CE, D} – мин-но.

  1. Создание объектов в языке C++. Распределение объектов в динамической памяти (куче) и автоматическое распределение памяти под объекты (на стеке). Сильные и слабые стороны.

В С++ распределение памяти для переменных осуществляется в стеке и в куче. Когда переменные распределяются в стеке, то при распределении вызывается их конструктор и при выходе их из области видимости вызывается их деструктор. Наибольшее распространение для объекта получил способ выхода из области видимости ч/з возврат функции. Например:

void main {

MyClass Object; // MyClass

SomeFunction(Object); // вызываем функцию SomeFunction с

// параметром типа MyClass

Return 0;}

В данном тексте сначала объект создается в стеке при объявлении (вызов конструктора), затем используется конструктор копирования для передачи параметра в функцию (в области видимости функции появляется экземпляр объекта типа MyClass), а затем переменная Object уничтожается (выход за пределы видимости – процедуры Main). Кроме того, деструктор вызывается в SomeFunction после возврата функции (оператора return).

Замечание: нет необходимости указывать ключевое слово auto перед объявлением имени переменной. Компилятор в его отсутствие автоматически определяет, что распределение идет на стеке. Пример аналогичных конструкций: 1) auto int a; 2) int a;

Второй способ – создание объекта в куче с использованием оператора new:

myClass *pObject = new MyClass;

someFunction(*pObject);

delete pObject;

Использование оператора new приводит к вызову конструктора класса myClass. Для передачи параметра в функцию надо разадресовать указатель pObject. Далее опять происходит вызов конструктора копирования и деструктора в теле функции. Delete pObject освобождает память. Если же определить функцию someFunction(myClass *c), в которую передается указатель на объект, то при ее использовании конструктор копии не будет вызван, т.к. new объект не создается. Поэтому и при возвращении управления функцией не вызывается деструктор.

Использование оператора new подразумевает необходимость освобождения памяти с помощью delete. Иначе происходит утечка памяти – область памяти, использованная для данного объекта, становится недоступной до окончания программы. Часто такие ошибки приводят к замедлению или даже завершению программы, они малозаметны. В случае обработки исключений необходимо дублировать операторы delete для всех используемых указателей, что не является идеальным решением. Кроме того, копирование указателей (Н-Р, при передаче их в функцию) усложняет управление памятью – может случайно удалить уже удаленный указатель. Для того, чтобы избежать таких ошибок, рекомендуется удаленные указатели устанавливать в NULL. Работа с указателями часто бывает небезопасна: передача указателя подразумевает возможность изменения объекта, что может быть нежелательно.

В свою очередь, использование автоматического распределения (в стеке) часто приводит к уменьшению производительности и доступной памяти: при каждой передаче объекта в функцию по значению создается копия этого объекта (конструктором копий), а при возврате управления функцией создается другая копия. Это занимает время и память. Во избежание этого рекомендуется использовать передачу указателя const. В этом случае копирование объекта не происходит, а объект не может быть изменен.