Си++: различия между версиями

Содержимое удалено Содержимое добавлено
Нет описания правки
Нет описания правки
Строка 7:
== Основные отличия Си++ от Си ==
 
=== Использование ссылок; передача аргументов по ссылке ===
 
==== Передача параметров в Си ====
Строка 73:
После этого <tt>z</tt> и <tt>x</tt> обозначают одно и то же — некую область в памяти, в которой хранится целое число. Заметим, что эти две строки принципиально отличаются.
 
Во-первых, мы можем написать «<tt>int z = 7;</tt>», а можем:
int z = 7;
а можем
int z;
z = 7;
Это будет практически одно и то же.
 
Ссылки ведут себя совсем иначе. Запись «<tt>int &x = z;</tt>» означает, что «<tt>x</tt> отныне является ссылкой на область памяти, которая раньше называлась <tt>z</tt>». В то же время запись «<tt>x = z;</tt>» означала бы, что области памяти, на которую ссылается <tt>x</tt>, нужно присвоить значение переменной <tt>z</tt>. В нашем случае (когда <tt>x</tt> ссылается на <tt>z</tt>) это эквивалентно записи «<tt>z = z;</tt>».
Ссылки ведут себя совсем иначе. Запись
int &x = z;
означает, что «<tt>x</tt> отныне является ссылкой на область памяти, которая раньше называлась <tt>z</tt>». В то же время запись
x = z;
означала бы, что области памяти, на которую ссылается <tt>x</tt>, нужно присвоить значение переменной <tt>z</tt>. В нашем случае (когда <tt>x</tt> ссылается на <tt>z</tt>) это эквивалентно записи
z = z;
 
Заметим, что когда мы пишем «<tt>int z;</tt>», то выделяется память для хранения величины типа <tt>int</tt>. А когда мы пишем
«<tt>int &x = z;</tt>», мы пользуемся «чужой» памятью, то есть памятью, выделенной когда-то кем-то.
int z;
то выделяется память для хранения величины типа <tt>int</tt>. А когда мы пишем
int &x = z;
мы пользуемся «чужой» памятью, то есть памятью, выделенной когда-то кем-то.
 
Когда время жизни переменной <tt>z</tt> заканчивается (в нашем примере — когда мы возвращаемся из <tt>main()</tt>), выделенная память освобождается. Если на неё остались какие-то указатели и ссылки — это ваши проблемы, и ваша программа непременно вскоре упадёт. У нас такого не происходит, потому что пока жива ссылка <tt>x</tt>, жива и переменная <tt>z</tt>.
Строка 120 ⟶ 110 :
теперь x == z == zz == 5 */
Изменить указатель, скрытый за ссылкой <tt>x</tt>, нельзя — просто нет в Си++ оператора, позволяющего это сделать.
 
Ещё одно важное отличие — ссылка не может ссылаться «ни на что». То есть, если указатель может иметь значение ''NULL'' (что, как известно, является просто красивым названием для числа 0), то ссылка — нет.
 
==== Зачем нужны ссылки? ====
 
Мы не смогли прийти к какому-либо глубокомысленному заключению. Ссылки просто местами удобнее. Придумать ситуацию, когда ссылку нельзя было бы заменить указателем, мне и моим знакомым не удалось.
 
=== Использование констант ===
 
==== Общие соображения =====
 
Константы — это совсем просто. Константа — это переменная, которую обязательно инициализировать и которая после этого не меняет своего значения.
 
Константы были ещё в Си, но их никто не использовал, ибо они были кривые. Числовые константы делали с помощью <tt>#define</tt>, и это неплохо работало. Константы всех остальных типов использовали редко.
 
В Си++ константы и всё, с ними связанное, получило религиозный статус с приходом классов. Но этого мы сейчас касаться не будем. Сейчас мы разберёмся, чем отличаются константы Си++ от констант Си.
 
…А главное отличие — их теперь можно использовать! Например, можно написать так:
const int N = 10;
int &xA = z[N];
Возможно, вы не поверите, но в Си этого сделать было нельзя. Хотя значение <tt>N</tt> известно во время компиляции, но в Си компилятор «закрывал на это глаза». (Безусловно, у них были свои причины на это, для интересующихся — причины зовут «extern», но всё равно получилось не очень хорошо.)
 
А раз константы можно использовать, отчего же этого не делать? Они многим лучше, чем <tt>#define</tt>:
* они имеют тип, а значит, позволяют «на халяву» найти парочку ошибок в вашей программе;
* они могут быть не просто числом или строкой, но и какой-нибудь сложной структурой;
* их имена можно использовать при отладке (хотя с современными средствами это почти не актуально);
* они не имеют ''побочных эффектов'' и других классических проблем с макросами (отсылаю вас к предостережениям о директиве <tt>#define</tt>, написанных в любой хорошей книге по Си или Си++).
 
Константы обязательно инициализировать, например:
const int foo = 10; /* можно */
/* const int bar; -- нельзя */
И это, дамы и господа, логично! Если мы её не инициализируем, то вообще никогда не сможем ничего ей присвоить, ведь она же константа. А на фиг тогда она была бы нам нужна?
 
===== Константы и ссылки/указатели =====
 
Константы очень интересно сочетаются с указателями и ссылками. По крайней мере, это интересно выглядит. Посмотрите сами:
 
; <tt>const int *foo</tt> : Указатель на <tt>const int</tt>. Значение указателя изменить можно (так, чтобы он указывал на что-нибудь другое), а вот значение переменной, ''на которую'' он указывает, менять нельзя.
 
; <tt>int *const foo = &x</tt> : Константный (неизменный) указатель на <tt>int</tt>. Значение указателя менять нельзя (прям как будто это ссылка, а не указатель). Значение того, на что он указывает, менять можно. Заметьте, что константный указатель обязательно инициализировать, как и любую другую константу.
 
; <tt>const int *const foo = &x</tt> : Смесь двух предыдущих пунктов. Ничего нельзя изменить: ни значение указателя, ни значение того, на что он указывает. Опять же, инициализация обязательна.
 
У ссылок разнообразия значительно меньше, ибо «указательная» часть ссылки и так всегда константна. Значит, бывает только:
const int &xfoo = zx;
— ссылка на <tt>int</tt>, который мы (с помощью этой ссылки) не сможем изменить.
 
И, наконец, пусть наши заявления про неизменность ссылок обретут некий формальный вид. Следующие строки очень похожи по смыслу:
int z&foo = 7x;
int *const bar = &x;
Фактически, после этого <tt>foo</tt> и <tt>bar</tt> отличаются только синтаксически (везде нужно писать <tt>*bar</tt>, но просто <tt>foo</tt>), и если мы везде заменим <tt>foo</tt> на <tt>*bar</tt> или наоборот, ничего не изменится.
 
=== Логический тип и перечисления ===
 
=== Операторы управления динамической памятью, инициализация массивов ===
 
=== Структура программы, раздельная компиляция и особенности использования статической памяти ===
 
=== Функциональный полиморфизм ===
 
=== Пространства имён и исключения ===
 
=== Библиотека ввода-вывода (<tt>iostream</tt>) ===
 
== Средства объектного программирования ==
 
== Средства объектно-ориентированного программирования ==
 
== Generic programming ==
 
== Стандартная библиотека ==