Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Элджер Д. - C++. Библиотека программиста - 1999.pdf
Скачиваний:
141
Добавлен:
13.08.2013
Размер:
1.98 Mб
Скачать

255

сталкиваемся со знакомой проблемой имитации указателей — раздражающей, но безвредной. Каждый раз, когда будет найдено значение, соответствующее адресу некоторого объекта, этот объект помечается и включается в рекурсию.

Внешние объекты

При управлении несколькими пространствами памяти можно встретить объекты, находящиеся не в главном пространстве, в котором происходит сборка мусора, а в другом пространстве по вашему выбору. Тот факт, что объект является внешним, не снимает с вас ответственности — он вполне может ссылаться обратно, в управляемое пространство. Если это пространство не было рассчитано на эффективный перебор указателей (то есть не имеет заголовков объектов), дальше выкручивайтесь сами.

Сборка мусора

Итак, к концу фазы пометки вы определили доступные объекты. Что же дальше? Без дескрипторов и ведущих указателей уплотнение неоправдано, поскольку не существует единого места, в котором можно было бы обновить адрес перемещаемого объекта. Теоретически можно сделать второй проход по памяти и обновить все указатели тем же способом, который использовался при пометке доступных объектов. Прежде чем это делать, закупите побольше акций производителей мощных RISCкомпьютеров: работы у них прибавится. Более практичное решение — организовать сборку мусора на месте.

Если вы не можете гарантировать, что все объекты происходят от общего предак, деструкторы лучше не вызывать (а если можете, то зачем использовать такую извращенную и ненадежную архитектуру?). Вполне может оказаться, что вы имеет дело с int или char*; никто не гарантирует, что у вашего объекта есть v-таблица! Не забывайте о том, что С++ — это все-таки не Lisp и не SmallTalk.

Последовательная сборка мусора

Алгоритмы пометки и удаления довольно трудно реализовать в последовательном варианте, но при должном внимании возможно и это. К сожалению, подробности выходят за рамки этой книги, но они относятся не к С++, а к выбранным вами конкретным алгоритмам.

Итоговые перспективы

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

Во-первых, лучший способ понять границы возможностей С++ и разобраться в его идиомах — залезть в дебри управления памятью. Даже если в ваших проектах это не нужно, хорошее понимание языковых ограничений и представления объектов в памяти только пойдет вам на пользу. В конце концов, это повысит вашу квалификацию в отладке, поскольку вы будете досконально понимать, как объекты хранятся в памяти.

Во-вторых, в один прекрасный день перед вами может возникнуть задача: организовать серьезное управление памятью по промышленным стандартам. Когда эта беда произойдет, вы будете к ней готовы. И помните, что эти главы не содержат конкретных решений, а лишь показывают, как реализуются на С++ алгоритмы, выкопанные пыли академических изданий. Все описанные приемы пригодятся, но мы лишь мимоходом коснулись этой обширной темы.

В-третьих, представьте себе вечеринку по С++. Вы ждете, когда окружающие придут в хорошее расположение духа, берете мартини и произносите ключевую фразу: «Помню, летом 95-го делали мы один проект на С++, и возникла задача: реализовать схему сборки мусора с уплотнением…» Развлекайтесь!

ПРИЛОЖЕНИЕ

Java против C++

При виде ажиотажа, поднятого вокруг Java, невольно возникает вопрос: а не является ли это обычной рекламной шумихой, единственная цель которой — заставить вас купить очередной язык, обновить компьютер и приобрести кучу книг? Верятно, вам приходилось видеть, как обозреватели в вашем любимом компьютерном журнале называют Java «новой версией» С++. Если это действительно так, то стоит ли вам, знатоку С++, беспокоиться об этом «новом» языке?

Java — это просто диалект С++. Кое-кто называет Java «вычищенным» вариантом С++, из которого убраны некоторые редко используемые и нелогичные возможности. Выходит, вы почти что знаете Java, не открыв ни одной книги. Тем не менее, у Java есть определенные аспекты, способные поколебать вашу уверенность. В этом приложении рассматриваются некоторые отличия между языками.

Забудьте о ручном управлении памятью, благодаря которому на С++ можно писать приложения, превосходящие Java-аналоги по быстродействию и более эффективно расходующие память. Разработчики Java ликвидировали ручное выделение и освобождение памяти (пример 1), стремясь снизить вероятность ошибок при кодировании.

Пример 1

int* pt = new int; delete pt;

Арифметические операции с указателями в Java отсутствуют (см. пример 2). Массивы Java представляют собой настоящие массивы, а не указатели, как в С++. Используемая в Java модель указателей фактически ликвидирует синтаксис указателей С++. Изменения были внесены для предотвращения случайных нарушений памяти и порчи данных из-за ошибочных смещений в арифметических операциях с указателями.

Пример 2

char* na = “Bob Smith” na++;

Java предотвращает утечки памяти за счет ее автоматического освобождения — своего рода автоматическая сборка мусора.

Кроме того, размер встроенных типов данных в Java не зависит от компилятора или типа компьютера, как в С++. Типы данных имеют фиксированный размер — скажем, int в Java всегда является 32разрядным числом (табл. 1). Компилятор Java генерирует инструкции байт-кода, которые эффективно преобразуются в набор машинных команд.

258

Таблица 1. Типы данных Java

Тип

Размер

int

4

байта

short

2

байта

long

8

байт

float

4

байта

double

8

байт

 

 

 

Кроме того, вы не встретите еще некоторых знакомых конструкций. Разработчики Java ликвидировали еще две конструкции, связанные с управлением памятью — структуры (см. пример 3) и объединения. Java не поддерживает этих синтаксических средств С++.

Пример 3

struct name {

char fname[20]; char lname[30];

}

Одна из задач Java заключалась в том, чтобы предотвратить динамические ошибки за счет ликвидации источника распространенных ошибок в С++. Среди таких ошибок — оператор присваивания (=), перепутанный с оператором равенства (==). В примере 4 показана распространенная ошибка С++, предотвращаемая компилятором Java.

Пример 4

if (value = 10)

Вы провели бесчисленные часы за разработкой изощренной иерархии множественного наследования и теперь желаете перенести ее в Java? Вас ждет некоторое разочарование. Принципиальное отличие между Java и С++ заключается в том, что Java не поддерживает множественного наследования из-за сложностей в управлении иерархиями. Тем не менее, в Java существуют интерфейсы, которые обладают преимуществами множественного наследования без тех затруднений, которые с ним связаны.

Остерегайтесь коварства Java! Этот язык полон ловушек для программистов на С++. Например классы Java похожи на С++. Тем не менее, все функции в Java (в том числе и main) должны принадлежать некоторому классу. В соответствии с требованиями Java для main необходимо создать класс-оболочку (см. пример 5). В Java нет функций классов, а есть методы, поэтому main — метод, а не функция

Пример 5

public class ShellClass

{

public static void main(Strings[] args)

{

}

}

Работа со строками в Java несколько запутанна. В С++ строка представляет собой массив символов, и вы можете модифицировать отдельные символы в строке. В Java дело обстоит иначе. Строки Java больше напоминают указатель char*. Строковые объекты Java удобны для программистов, поскольку они автоматически выделяют и освобождают память. Это происходит в операторе присваивания, в конструкторе и деструкторе.

Методы Java похожи на функции классов С++, но все же не идентичны им. Например, в Java нет глобальных функций и прототипов функций. Компилятор Java работает в несколько проходов, что

259

позволяет использовать методы до их определения. Более того, функции нельзя передать адрес переменной, поскольку аргументов-указателей и ссылок в Java не существует.

Некоторые части Java узнаются с первого взгляда. Например, объектные переменные Java аналогичны объектым указателям С++ (см. пример 6). Объекты Java находятся в куче, а объект, содержащий объектную переменную другого объекта, на самом деле указывает на другой объект в куче.

Пример 6

//Java MyObject ob1;

//C++ MyObject* ob1;

Методы Java должны определяться внутри класса. Внешнее определение, как в С++, не допускается. Фрагмент, показанный в примере 7, работает в С++, но не в Java. Хотя методы определяются внутри класса, это не значит, что они автоматически становятся подставляемыми (inline) функциями.

Пример 7

class Person

{

};

void Person::Raise()

{

salary *= 1000

}

Стоит ли бросать С++ и переходить на Java? Трудно сказать. Java заслуживает пристального внимания при разработке приложений для Internet, корпоративных или внешних сетей. Библиотека Java содержит все средства, необходимые для работы с протоколами TCP/IP, HTTP и FTP. Благодаря этому обратиться к сетевому объекту по URL так же просто, как и в локальной файловой системе.

Язык Java архитектурно нейтрален, поскольку копилятор генерирует объектный код и делает Javaприложения независимыми от реализации. Это особенно важно для Internet-приложений. Однако в Java вам не удастся использовать средства управления памятью С++, чтобы выжать все возможное быстродействие для данной платформы. Так приходится расплачиваться за управление памятью, переданное в распоряжение Java.

Как только речь заходит о многопоточности, архитектурная нейтральность Java исчезает. Многопоточный код архитектурно нейтрален, но для реализации многопоточности Java прибегает к услугам операционной системы, поскольку реализация программных потоков существенно различается на разных платформах.

Произведет ли Java революцию в языках программирования? Станет ли это концом С++? Не спешите выбрасывать свой компилятор С++. При разработке приложений для Internet, а также корпоративных и внешних сетей Java оказывается более простым и удобным языком, чем С++. И все же вопрос о том, удастся ли Java стать действительно всесторонним языком и переманить на свою сторону программистов, остается открытым.

Соседние файлы в предмете Программирование на C++