Вход/Регистрация
Программирование. Принципы и практика использования C++ Исправленное издание
вернуться

Страуструп Бьерн

Шрифт:

Итак, мы не хотим передавать функциям встроенные массивы с помощью указателей и размера массива. Чем это заменить? Проще всего передать ссылку на контейнер, например, на объект класса vector. Проблема, которая возникла в связи с интерфейсом функции

void poor(Shape* p, int sz);

исчезает при использовании функции

void general(vector<Shape>&);

Если вы программируете систему, в которой допускаются объекты класса

std::vector
(или его эквиваленты), то просто последовательно используйте в интерфейсах класс
vector
(или его эквиваленты) и никогда не передавайте встроенный массив с помощью указателя и количества элементов.

Если вы не можете ограничиться использованием класса

vector
или его эквивалентов, то оказываетесь на территории, где не бывает простых решений, — даже несмотря на то, что использование класса (
Array_ref
) вполне очевидно.

25.4.3. Решение: интерфейсный класс

К сожалению, во многих встроенных системах мы не можем использовать класс

std::vector
, потому что он использует свободную память. Мы можем решить эту проблему, либо предложив особую реализацию класса
vector
, либо (что более просто) используя контейнер, напоминающий класса
vector
, но не содержащий его механизма управления памятью. Прежде чем описать такой интерфейсный класс, перечислим его желательные свойства.

• Он ссылается на объекты в памяти (он не владеет объектами, не размещает их, не удаляет и т.д.).

• Он знает свой размер (а значит, способен проверять выход за пределы допустимого диапазона).

• Он знает точный тип своих элементов (а значит, не может порождать ошибки, связанные с типами).

• Его несложно передать (скопировать) как пару (указатель, счетчик).

• Его нельзя неявно преобразовать в указатель.

• Он позволяет легко выделить поддиапазон в целом диапазоне.

• Его легко использовать как встроенный массив.

Свойство “легко использовать как встроенный массив” можно обеспечить лишь приблизительно. Если бы мы сделали это совершенно точно, то вынуждены были бы смириться с ошибками, которых стремимся избежать.

Рассмотрим пример такого класса.

template<class T>

class Array_ref {

public:

Array_ref(T* pp, int s) :p(pp), sz(s) { }

T& operator[ ](int n) { return p[n]; }

const T& operator[ ](int n) const { return p[n]; }

bool assign(Array_ref a)

{

if (a.sz!=sz) return false;

for (int i=0; i<sz; ++i) { p[i]=a.p[i]; }

return true;

}

void reset(Array_ref a) { reset(a.p,a.sz); }

void reset(T* pp, int s) { p=pp; sz=s; }

int size const { return sz; }

// операции копирования по умолчанию:

// класс Array_ref не владеет никакими ресурсами

// класс Array_ref имеет семантику ссылки

private:

T* p;

int sz;

};

Класс

Array_ref
близок к минимальному.

• В нем нет функций

push_back
(для нее нужна динамическая память) и
at
(для нее нужны исключения).

• Класс Array_ref имеет форму ссылки, поэтому операция копирования просто копирует пары (

p, sz
).

• Инициализируя разные массивы, можем получить объекты класса

Array_ref
, которые имеют один и тот же тип, но разные размеры.

• Обновляя пару (

p, size
) с помощью функции
reset
, можем изменить размер существующего класса
Array_ref
(многие алгоритмы требуют указания поддиапазонов).

• В классе

Array_ref
нет интерфейса итераторов (но при необходимости этот недостаток легко устранить). Фактически концепция класса
Array_ref
очень напоминает диапазон, заданный двумя итераторами.

Класс

Array_ref
не владеет своими элементами и не управляет памятью, он просто представляет собой механизм для доступа к последовательности элементов и их передачи функциям. Иначе говоря, он отличается от класса
array
из стандартной библиотеки (см. раздел 20.9).

  • Читать дальше
  • 1
  • ...
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: