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

1 ... 111 112 113 [ 114 ] 115 116 117 ... 395


Matrix& grow( Matrix* p ) { Matrix *res;

в1деим память для объекта Matrix большого размера res адресует этот нов объект

скопируем содержим return *res;

скопируем содержимое *p в *res

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

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

возврат ссылки на локальный объект, время жизни которого ограничено временем выполнения функции. (О времени жизни локальных объектов речь пойдет в разделе 8.3.) По завершении функции такой ссылке соответствует область

/ / ошибка: возврат сс1лки на локальн объект Matrix& add( Matrix &m1, Matrix &m2 ) {

Matrix result:

if ( m1.isZero() )

return m2; if ( m2.isZero() )

return m1;

сложим содержимое двух матриц

ошибка: сс1лка на сомнительна область памяти после возврата return result;

памяти, содержащая неопределенное значение. Например:

В таком случае тип возврата не должен быть ссылкой. Тогда локальная переменная может быть скопирована до окончания времени своей жизни:

Matrix add( ... )

функция возвращает l-значение. Любая его модификация затрагивает сам объект. Например:



#include <vector>

int sget val( vector<int> svi, int ix ) { return vi [ix];

int ai[4] = { 0, 1, 2, 3 };

vector<int> vec( ai, ai+4 ); копируем 4 элемента ai в vec

int main() {

увеличивает vec[0] на 1 get val( vec.0 )++;

...

Для предотвращения нечаянной модификации возвращенного объекта нужно объявить тип возврата как const:

const int sget val( ... )

Примером ситуации, когда l-значение возвращается намеренно, чтобы позволить модифицировать реальный объект, может служить перегруженный оператор взятия индекса для класса IntArray из раздела 2.3.

7.4.1. Передача данных через параметры и через глобальные объекты

Различные функции программа: могут общаться между собой с помощью двух механизмов. (Под словом общаться м1 подразумеваем обмен данными.) В одном случае используются глобальные объекты, в другом - передача параметров и возврат значений.

int glob; int main() {

что угодно

Глобальн1й объект определен вне функции. Например:

Объект glob является глобальным. (В главе 8 рассмотрение глобальных объектов и глобальной области видимости будет продолжено.) Главное достоинство и одновременно один из наиболее заметных недостатков такого объекта - доступность из любого места программы, поэтому его обычно используют для общения между разными модулями. Обратная сторона медали такова:

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

при модификации такой программы повышается вероятность ошибок. Даже для внесения локальных изменений необходимо понимание всей программы в целом;



vector<string> &readText( vector<string> text;

) {

string word; while ( cin >> word ) {

text.push back( word );

... ....

return text;

Найдите в данной функции потенциальную ошибку времени выполнения:

Упражнение 7.11

Каким способом вы вернули бы из функции несколько значений? Опишите достоинства и недостатки вашего подхода.

если глобальный объект получает неверное значение, ошибку нужно искать по всей программе. Отсутствует локализация;

используя глобальные объекты, труднее писать рекурсивные функции (Рекурсия возникает тогда, когда функция вызывает сама себя. Мы рассмотрим это в разделе 7.5.);

если используются потоки (threads), то для синхронизации доступа к глобальным объектам требуется писать дополнительный код. Отсутствие синхронизации - одна из раснространенн1х ошибок при использовании потоков. (Пример использования потоков при программировании на С++ см. в статье Distributing Object Computing in C++ (Steve Vinoski and Doug Schmidt) в [LIPPMAN96b].)

Можно сделать вывод, что для передачи информации между функциями предпочтительнее пользоваться параметрами и возвращаемыми значениями.

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

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

Упражнение 7.9

Каковы две форм: инструкции return? Объясните, в каких случаях следует использовать первую, а в каких вторую форму.

Упражнение 7.10



1 ... 111 112 113 [ 114 ] 115 116 117 ... 395

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