Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
c++book1.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
2 Мб
Скачать
☆

4.6.4 Возврат Значения

Из функции, которая не описана как void, можно (и долж­но) возвращать значение. Возвращаемое значение задается опе­ратором return. Например:

int fac(int n) (*return (n>1) ? n*fac(n-1) : 1; *)

В функции может быть больше одного оператора return: int fac(int n)

(*

if (n > 1)

return n*fac(n-1);

else

return 1;

*)

Как и семантика передачи параметров, семантика возврата функцией значения идентична семантике инициализации. Возвра­щаемое значение рассматривается как инициализатор переменной возвращаемого типа. Тип возвращаемого выражения проверяется на согласованность с возвращаемым типом и выполняются все стандартные и определенные пользователем преобразования ти­пов. Например:

double f()

(*

// ...

return 1; // неявно преобразуется к double(1)

*)

Каждый раз, когда вызывается функция, создается новая копия ее параметров и автоматических переменных. После возв­рата из функции память используется заново, поэтому возвра­щать указатель на локальную переменную неразумно. Содержание указываемого места изменится непредсказуемо:

int* f() (*

int local = 1;

// ...

return &local; // так не делайте

*)

Эта ошибка менее обычна, чем эквивалентная ошибка при использовании ссылок:

int& f() (*

int local = 1;

// ...

return local; // так не делайте

*)

К счастью, о таких возвращаемых значениях предупреждает компилятор. Вот другой пример:

int& f() (* return 1;*) // так не делайте

4.6.5 Векторные Параметры

Если в качестве параметра функции используется вектор, то передается указатель на его первый элемент. Например:

int strlen(const char*);

void f()

(*

char v[] = "a vector"

strlen(v);

strlen("Nicholas");

*);

Иначе говоря, при передаче как параметр параметр типа T[] преобразуется к T*. Следовательно, присваивание элементу векторного параметра изменяет значение элемента вектора, ко­торый является параметром. Другими словами, вектор отличается от всех остальных типов тем, что вектор не передается (и не может передаваться) по значению.

Размер вектора недоступен вызываемой функции. Это может быть неудобно, но эту сложность можно обойти несколькими спо­собами. Строки оканчиваются нулем, поэтому их размер можно легко вычислить. Для других векторов можно передавать второй параметр, который задает размер, или определить тип, содержа­щий указатель и индикатор длины, и передавать его вместо просто вектора (см. также #1.11). Например:

Void compute1(int* vec_ptr, int vec_size); // один способ

struct vec (* // другой способ

int* ptr;

int size;

*);

void compute2(vec v);

С многомерными массивами все хитрее, но часто можно вместо них использовать векторы указателей, которые не требу­ют специального рассмотрения. Например:

char* day[] = (*

"mon", "tue", "wed", "thu", "fri", "sat", "sun"

*);

С другой стороны, рассмотрим определение функции, кото­рая работает с двумерными матрицами. Если размерность извест­на на стадии компиляции, то никаких проблем нет:

void print_m34(int m[3][4])

(*

for (int i = 0; i<3; i++) (*

for (int j = 0; j<4; j++)

cout << " " << m[i][j];

cout << "\n";

*)

*)

Матрица, конечно, все равно передается как указатель, а размерности используются просто для удобства записи.

Первая размерность массива не имеет отношения к задаче поиска положения элемента (#2.3.6). Поэтому ее можно переда­вать как параметр:

void print_mi4(int m[][4], int dim1)

(*

for (int i = 0; i<dim1; i++) (*

for (int j = 0; j<4; j++)

cout << " " << m[i][j];

cout << "\n";

*)

*)

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

void print_mij(int m[][], int dim1, int dim2) // ошибка

(*

for (int i = 0; i<dim1; i++) (*

for (int j = 0; j<dim2; j++)

cout << " " << m[i][j]; // сюрприз!

cout << "\n";

*)

*)

Во-первых, описание параметра m[][] недопустимо, пос­кольку для нахождения положения элемента должна быть известна вторая размерность многомерного массива. Во-вторых, выражение m[i][j] интерпретируется (правильно) как *(*(m+i)+j), но не­похоже, чтобы это имел в виду программист. Вот правильное ре­шение:

void print_mij(int** m, int dim1, int dim2)

(*

for (int i = 0; i<dim1; i++) (*

for (int j = 0; j<dim2; j++)

cout << " " << (int*)m[i*dim2+j]; // туманно cout << "\n";

*)

*)

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

int* v = (int*)m;

// ...

v[i*dim2+j]

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]