Программирование >>  Полиморфизм без виртуальных функций в с++ 

1 ... 26 27 28 [ 29 ] 30 31 32 ... 144


Модификатор readonly служит для предотврощения изменения переменной. Он показы-воет, что из всех способов доступа к переменной зоконны только те, которые не изменяют ее значения .

Далее в записке говорится:

Модификатор readonly применим также и кукозотелям. * readonly интерпретируется как неизменяемый указатель но . Например:

readonly int * р; /* указатель на int только для чтения */ int * readonly pp; /* неизменяемый указатель на int */ readonly int * readonly ppp; /* неизменяемый указатель на */

/* int только для чтения */

В этих примерах допустимо присвоить новое значение р, но не *р. Можно присвоить зно-чение *рр, но не pp. Ни ррр, ни *ррр зночение присвоить нельзя .

В той же записке введено понятие о writeonly:

Модификотор типо writeonly анологичен readonly, только зопрещает чтение, о не зопись. Нопример:

struct device registers {

readonly int input reg, status reg; writeonly int output reg, coiiimand reg;

void f(readonly char * readonly from, writeonly char * readonly to)

f может получить данные через from, сохранить результаты в to,

но не может изменить ни тот, ни другой указатель

/* ... */

int * writeonly р;

Здесь ++Р недопустимо, ток как в кочестве побочного эффекте подразумевает чтение предыдущего значения р, но р=0 допустимо .

Это предложение акцентировало внимание на определении интерфейса, а не на включении в С символических констант. Ясно, что значение с модификатором readonly - это символическая константа, но идея была шире. Первоначально я предлагал указатели на readonly, но не readonly-указатели. Благодаря короткой дискуссии с Деннисом Ричи возникла идея о механизме readonly/ writeonly, который был реализован и предложен внутренней группе по стандартизации С в стенах Bell Labs под председательством Ларри Рослера. Это мой первый опыт работы над стандартами. Покидая совещание, я имел договоренность (то есть принятое большинством решение), что readonly будет включено в С -да-да, именно в С, а не в С with Classes или С++, следует только переименовать его в const. К сожалению, подобные решения ни к чему не обязывают, вот почему



с нашими компиляторами С ничего не произошло. Позже был образован комитет ANSI С (X3J11), предложение о введении const было представлено на его рассмотрение и стало частью ANSI/ISO С.

Между тем я продолжил эксперименты с const в С with Classes и обнаружил, что этот модификатор может служить заменой макросам для представления констант, только если глобальные const-объекты используются как локальные в своих единицах компиляции. Лишь в этом случае компилятор мог без труда сделать вывод, что значение const-объектов действительно не изменится. Знание этого факта позволяет использовать простые const-объекты в константных выражениях, не выделяя под них память. В С это правило оказалось непринятым. Например, в С-ы- можно написать

const int max = 14,-

void f{int i)

int a[max+l]; константа max используется в константном выражении

switch (i) {

case max: константа max используется в константном выражении

...

тогда как в С (даже сегодня) необходимо

fdefine max 14 ...

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

3.9. Управление памятью

Задолго до того как была написана первая программа на С with Classes, я знал, что свободная (динамическая) память в языке с классами будет использоваться гораздо интенсивнее, чем в С. По этой причине в С with Classes и были введены операторы new и delete. Оператор new, который одновременно выделяет память и инициализирует ее, заимствован из языка Simula. Оператор delete был необходимым дополнением, поскольку я не хотел, чтобы С with Classes зависел от сборщика мусора (см. разделы 2.13 и 10.7). Изложу аргументацию в пользу оператора new. Какая запись вам больше нравится, такая:

X* р = new X(2);



struct X * р = (struct X *) malloc(sizeof(struct X)); if (p == 0) еггогСне хватило памяти ); p->init(2);

И где проще сделать ошибку? Отметим, что проверка на нехватку памяти ведется в обоих случаях. Только оператор new при выделении памяти делает это неявно и может вызывать написанную пользователем функцию new handler [2nd, §9.4.3]. В то время достаточно часто звучали аргументы против: нам это ни к чему и ведь кто-то мог уже использовать new как идентификатор . Разумеется, и то, и другое правильно.

Итак, введение оператора new упростило работу со свободной памятью и сделало ее менее подверженной ошибкам. Это способствовало широкому распространению оператора, поэто.му из-за функции выделения па.мяти malloc () из библиотеки С, использованной в реализации new, значительно снижалась производительность программы. Само по себе это не удивительно; вопрос - что с .этим делать? То, что реальные программы тратили 50% времени и даже больше внутри malloc (), было абсолютно неприемлемым.

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

Вспо.минаю, как излагал Брайану Кернигану и Дугу Макилрою прием присваивания указателю this (описан ниже) и резюмировал свою речь так: Это уродливо, как смертный грех, но работает, и если у вас нет лучших предложений, то именно так я это и реализую . Предложений у них не оказалось, так что более красивого решения нам пришлось ждать до выхода версии 2.0, уже в С++ (см. раздел 10.2).

По умолчанию память для объекта выделялась системой , не требуя от пользователя никаких действий. Чтобы отменить это, программист просто должен был присвоить значение указателю this. По определению this указывает на объект, для которого вызвана функция-член. Например:

class X {

... public:

x(int i);

. . .

X::X(int i)

this = my alloc(sizeof(X)); инициализация



1 ... 26 27 28 [ 29 ] 30 31 32 ... 144

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика