|
|||||||
АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция |
Ссылочный тип
Ссылочный тип, иногда называемый псевдонимом, служит для задания объекту дополнительного имени. Ссылка позволяет косвенно манипулировать объектом, точно так же, как это делается с помощью указателя. Однако эта косвенная манипуляция не требует специального синтаксиса, необходимого для указателей. Обычно ссылки употребляются как формальные параметры функций. В этом разделе мы рассмотрим самостоятельное использование объектов ссылочного типа. Хотя, как мы говорили, ссылка очень похожа на указатель, она должна быть инициализирована не адресом объекта, а его значением. Таким объектом может быть и указатель: int ival = 1024; // ошибка: refVal имеет тип int, а не int*int &refVal = &ival;int *pi = &ival;// правильно: ptrVal - ссылка на указательint *&ptrVal2 = pi;Определив ссылку, вы уже не сможете изменить ее так, чтобы работать с другим объектом (именно поэтому ссылка должна быть инициализирована в месте своего определения). В следующем примере оператор присваивания не меняет значения refVal, новое значение присваивается переменной ival – ту, которую адресует refVal. int min_val = 0;// ival получает значение min_val,// а не refVal меняет значение на min_valrefVal = min_val;Все операции со ссылками реально воздействуют на адресуемые ими объекты. В том числе и операция взятия адреса. Например: refVal += 2;прибавляет 2 к ival – переменной, на которую ссылается refVal. Аналогичноint ii = refVal;присваивает ii текущее значение ival,int *pi = &refVal;инициализирует pi адресом ival.Если мы определяем ссылки в одной инструкции через запятую, перед каждым объектом типа ссылки должен стоять амперсанд (&) – оператор взятия адреса (точно так же, как и для указателей). Например: // определено два объекта типа intint ival = 1024, ival2 = 2048; // определена одна ссылка и один объектint &rval = ival, rval2 = ival2; // определен один объект, один указатель и одна ссылкаint inal3 = 1024, *pi = ival3, &ri = ival3; // определены две ссылкиint &rval3 = ival3, &rval4 = ival2; Константная ссылка может быть инициализирована объектом другого типа (если, конечно, существует возможность преобразования одного типа в другой), а также безадресной величиной – такой, как литеральная константа. Например: double dval = 3.14159; // верно только для константных ссылокconst int &ir = 1024; const int &ir2 = dval; const double &dr = dval + 1.0; Если бы мы не указали спецификатор const, все три определения ссылок вызвали бы ошибку компиляции. Однако, причина, по которой компилятор не пропускает таких определений, неясна. Попробуем разобраться. то компилятор преобразует это примерно так: int temp = dval;const int &ri = temp;Если бы мы могли присвоить новое значение ссылке ri, мы бы реально изменили не dval, а temp. Значение dval осталось бы тем же, что совершенно неочевидно для программиста. Поэтому компилятор запрещает такие действия, и единственная возможность проинициализировать ссылку объектом другого типа – объявить ее как const. int *&pi_ref = &ival; Попытка исправить дело добавлением спецификатора const тоже не проходит: const int ival = 1024;// все равно ошибкаconst int *&pi_ref = &ival;В чем причина? Внимательно прочитав определение, мы увидим, что pi_ref является ссылкой на константный указатель на объект типа int. А нам нужен неконстантный указатель на константный объект, поэтому правильной будет следующая запись: const int ival = 1024;// правильноint *const &piref = &ival; Между ссылкой и указателем существуют два основных отличия. Во-первых, ссылка обязательно должна быть инициализирована в месте своего определения. Во-вторых, всякое изменение ссылки преобразует не ее, а тот объект, на который она ссылается. Рассмотрим на примерах. Если мы пишем: int *pi = 0;мы инициализируем указатель pi нулевым значением, а это значит, что pi не указывает ни на какой объект. В то же время запись const int &ri = 0; Что касается операции присваивания, то в следующем примере: int ival = 1024, ival2 = 2048;int *pi = &ival, *pi2 = &ival2;pi = pi2;переменная ival, на которую указывает pi, остается неизменной, а pi получает значение адреса переменной ival2. И pi, и pi2 и теперь указывают на один и тот же объект ival2. то само значение ival меняется, но ссылка ri по-прежнему адресует ival. bool get_next_value(int &next_value);// перегруженный операторMatrix operator+(const Matrix&, const Matrix&); Как соотносятся самостоятельные объекты-ссылки и ссылки-параметры? Если мы пишем: int ival;while (get_next_value(ival))...это равносильно следующему определению ссылки внутри функции: Поиск по сайту: |
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Студалл.Орг (0.004 сек.) |