|
Программирование >> Инициализация объектов класса, структура
class Type { }; void operate( const Types p1, const Types p2 ); int main() { Type obj1; присвоим objl некоторое значение ошибка: ссылка не может быть равной 0 Type obj2 = operate( objl, 0 ); объект. Например: Если параметр должен ссылаться на разные объекты во время выполнения функции или принимать нулевое значение (ни на что не ссылаться), нам следует использовать указатель. Одна из важнейших сфер применения параметров-ссылок - эффективная реализация перегруженных операций. При этом использование операций остается простым и интуитивно понятным. (Подробнее данный вопрос рассматривается в главе 15.) Разберем маленький пример. Представим себе класс Matrix (матрица). Хорошо бы реализовать Matrix a, b, c; операции сложения и присваивания привычным способом: c = a + b; Эти операции реализуются с помощью перегруженных операторов - функций с немного необычным именем. Для оператора сложения такая функция будет называться Matrix тип возврата - Matrix operator+( имя перегруженного оператора Matrix m1, тип левого операнда Matrix m2 тип правого операнда Matrix result; необходимые действия return result; operator+. Посмотрим, как ее определить: При такой реализации сложение двух объектов типа Matrix выглядит вполне привычно: a + b; но, к сожалению, оказывается совершенно неэффективным. Заметим, что параметры у нас передаются по значению. Содержимое двух матриц будет копироваться в область активации функции operator+() , а поскольку объекты типа Matrix весьма велики, затраты времени и памяти на создание копий могут быть совершенно неприемлемыми. Параметр-ссылка не нуждается в этой проверке, так как всегда существует именуемый ею реализация с параметрами-указателями operator+( Matrix *ml, Matrix *m2 ) { Matrix result; необходимхе действия return result; избежать этих затрат. Вот модифицированный код operator+() : Да, мы добились эффективной реализации, но зато теперь применение нашей операции вряд ли можно назвать интуитивно понятным. В качестве значений параметров-указателей требуется передавать адреса складываемых объектов. Поэтому для сложения двух матриц пришлось бы написать: &a + &b; допустимо, хотя и плохо Хотя такая форма не может не вызвать критику, но все-таки два объекта сложить еще а вот это не работает &a + &b возвращает объект типа Matrix удается. А вот три уже крайне затруднительно: &a + &b + &c; правильно: работает, однако ... Для того чтобы сложить три объекта, при подобной реализации нужно написать так: &( &a + &b ) + &c; Трудно ожидать, что кто-нибудь согласится писать такие выражения. К счастью, параметры-ссылки дают именно то решение, которое требуется. Если параметр объявлен как ссылка, функция получает его l-значение, а не копию. Лишнее копирование исключается. И тин фактического аргумента может быть Matrix - это упрощает операцию сложения, как и для встроенных типов. Вот схема перегруженного оператора реализация с параметрами-сс1лками operator+( const Matrix &m1, const Matrix &m2 ) Matrix result; необходимхе действия return result; сложения для класса Matrix: При такой реализации сложение трех объектов Matrix выглядит вполне привычно: Представим себе, что мы решили использовать указатели в качестве параметров, чтобы / / три эквивалентн1х объявления putValues() void putValues( int* ); void putValues( int[] ); эквивалентны: void putValues( int[ 10 ] ); Передача массивов как указателей имеет следующие особенности: изменение значения аргумента внутри функции затрагивает сам переданный объект, а не его локальную копию. Если такое поведение нежелательно, программист должен позаботиться о сохранении исходного значения. Можно также при объявлении функции указать, что она не должна изменять значение параметра, объявив этот параметр константой: void putValues( const int[ 10 ] ); размер массива не является частью типа параметра. Поэтому функция не знает реального размера передаваемого массива. Компилятор тоже не может это void putValues( int[ 10 ] ); рассматривается как int* int main() { int i, j [ 2 ]; putValues( si ); правильно: si is int*; однако при выполнении возможна ошибка putValues( j ); правильно: j - адрес 0-го элемента - int*; проверить. Рассмотрим пример: однако при выполнении возможна ошибка При проверке типов параметров компилятор способен распознать, что в обоих случаях тип аргумента int* соответствует объявлению функции. Однако контроль за тем, не является ли аргумент массивом, не производится. a + b + c; Ссылки были введены в С++ именно для того, чтобы удовлетворить двум требованиям: эффективная реализация и интуитивно понятное применение. 7.3.3. Параметры-массивы Массив в С++ никогда не передается по значению, а только как указатель на его первый, точнее нулевой, элемент. Например, объявление void putValues( int[ 10 ] ); рассматривается компилятором так, как будто оно имеет вид void putValues( int* ); Размер массива неважен при объявлении параметра. Все три приведенные записи
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |