Читаем C++ полностью

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

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

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

int* f() (* int local = 1; // ... return amp;local; // так не делайте *)

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

int amp; f() (* int local = 1; // ... return local; // так не делайте *)

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

int amp; 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]

4.6.6 Параметры по Умолчанию

Часто в самом общем случае функции требуется больше праметров, чем в самом простом и более употребительном случае. Например, в библиотеке потоков есть функция hex(), порождащая строку с шестнадцатиричным представлением целого. Второй параметр используется для задания числа символов для предтавления первого параметра. Если число символов слишком мало для представления целого, происходит усечение, если оно сликом велико, то строка дополняется пробелами. Часто програмист не заботится о числе символов, необходимых для предсталения целого, поскольку символов достаточно. Поэтому для нуля в качестве второго параметра определено значение «использвать столько символов, сколько нужно». Чтобы избежать засорния программы вызовами вроде hex(i,0), функция описывается так:

extern char* hex(long, int =0);

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
C++ Primer Plus
C++ Primer Plus

C++ Primer Plus is a carefully crafted, complete tutorial on one of the most significant and widely used programming languages today. An accessible and easy-to-use self-study guide, this book is appropriate for both serious students of programming as well as developers already proficient in other languages.The sixth edition of C++ Primer Plus has been updated and expanded to cover the latest developments in C++, including a detailed look at the new C++11 standard.Author and educator Stephen Prata has created an introduction to C++ that is instructive, clear, and insightful. Fundamental programming concepts are explained along with details of the C++ language. Many short, practical examples illustrate just one or two concepts at a time, encouraging readers to master new topics by immediately putting them to use.Review questions and programming exercises at the end of each chapter help readers zero in on the most critical information and digest the most difficult concepts.In C++ Primer Plus, you'll find depth, breadth, and a variety of teaching techniques and tools to enhance your learning:• A new detailed chapter on the changes and additional capabilities introduced in the C++11 standard• Complete, integrated discussion of both basic C language and additional C++ features• Clear guidance about when and why to use a feature• Hands-on learning with concise and simple examples that develop your understanding a concept or two at a time• Hundreds of practical sample programs• Review questions and programming exercises at the end of each chapter to test your understanding• Coverage of generic C++ gives you the greatest possible flexibility• Teaches the ISO standard, including discussions of templates, the Standard Template Library, the string class, exceptions, RTTI, and namespaces

Стивен Прата

Программирование, программы, базы данных