Программирование >>  Инициализация объектов класса, структура 

1 ... 105 106 107 [ 108 ] 109 110 111 ... 395


#include <vector>

параметр-сс1лка occurs

содержит второе возвращаемое значение

vector<int>::const iterator look up( const vector<int> &vec,

int value, искомое значение

int &occurs ) количество вхождений

res iter инициализируется значением следящего за конечн элемента vector<int>::const iterator res iter = vec.end(); occurs = 0;

for ( vector<int>::const iterator iter = vec.begin(); iter != vec.end();

++iter ) if ( *iter == value )

if ( res iter == vec.end() )

res iter = iter; ++occurs;

return res iter;

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

tuff[1000]; };

class Huge { public: double s extern int calc( const Huge &

int main() {

Huge table[ 1000 ] ;

... инициализация table

int sum = 0;

for ( int ix=0; ix < 1000; ++ix )

calc () сс1лается на элемент массива

типа Huge sum += calc( tab1e[ix] );

копии. Например:

Может возникнуть желание использовать нараметр-сс1лку, чтобы избежать создания копии большого объекта, но в то же время не дать вызываемой функции возможности изменять значение аргумента. Если параметр-ссылка не должен модифицироваться внутри функции, то стоит объявить его как ссылку на константу. В такой ситуации



class X;

extern int foo bar( X& );

int foo( const X& xx ) {

ошибка: константа передается функции с параметром неконстантного типа return foo bar( xx );

сигнализирует об ошибке:

Для того чтобы программа компилировалась, мы должна: изменить тип параметра

extern int foo bar( const X& );

foo bar() . Подойдет любой из следующих двух вариантов:

extern int foo bar( X ); передача по значению

int foo( const X &xx ) { ...

X x2 = xx; создать копию значения

foo bar() может поменять x2, xx останется нетронутым return foo bar( x2 ); правильно

Вместо этого можно передать копию xx, которую позволено менять:

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

void ptrswap( int *&vl, int *&v2 ) int *trnp = v2;

v2 = vl;

vl = tmp;

функции, обменивающей друг с другом значения двух указателей:

Объявление

int *&v1;

компилятор способен распознать и пресечь попытку непреднамеренного изменения значения аргумента.

В следующем примере нарушается константность параметра xx функции foo() . Поскольку параметр функции foo bar() не является ссылкой на константу, то нет гарантии, что вызов foo bar() не изменит значения аргумента. Компилятор



должно читаться справа налево: v1 является ссылкой на указатель на объект типа int. Модифицируем функцию main() , которая вызывала rswap() , для проверки работы

#include <iostream>

void ptrswap( int *&vl, int *&v2 );

int main() {

int i = 10; int j = 20;

int *pi = &i; int *pj = &j;

cout << Перед ptrswap():\tpi:

<< *pi << \tpj: << *pj << endl;

ptrswap( pi, pj );

cout << После ptrswap():\tpi:

<< *pi << \tpj: << pj << endl;

return 0;

ptrswap() :

Вот результат работы программы:

Перед ptrswap(): pi: 10 pj: 20

После ptrswap(): pi: 20 pj: 10

7.3.2. Параметры-ссылки и параметры-указатели

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

Как было сказано в разделе 3.6, ссылка может быть один раз инициализирована значением объекта, и впоследствии изменить ее нельзя. Указатель же в течение своей жизни способен адресовать разные объекты или не адресовать вообще.

Поскольку указатель может содержать, а может и не содержать адрес какого-либо

class X;

void manip( X *px ) {

проверим на 0 перед использованием if ( px != 0 )

обратимся к объекту по адресу...

объекта, перед его использованием функция должна проверить, не равен ли он нулю:



1 ... 105 106 107 [ 108 ] 109 110 111 ... 395

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