Программирование >>  Структурное программирование 

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



f пытается выполнить незаконную модификацию

return 0;

1 в f аргумент xPtr - указатель на целую константу void f(const int *xPtr) {

*xPtr = 100; нельзя модифицировать константный объект

Compiling F105 12.CPP: Error FIG5 12.CPP 19: Cannot modify a const object

Warning FIG5 12.CPP 20 : Parameter xPtr is never used

Рис. 5.12. Попытка модифицировать данные, переданные посредством неконстантного указателя на константные данные

Совет по повышению эффективности 5.1

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

Константный указатель на неконстантные данные - это указатель, который всегда указывает на одну и ту же ячейку памяти, данные в которой можно модифицировать посредством указателя. Этот вариант реализуется по умолчанию для имени массива. Имя массива - это константный указатель

функции с массивом как аргументом массив автоматически передается функции с помощью моделирования передачи по ссылке. Однако, структуры всегда передаются вызовом по значению - передается копия всей структуры в целом. Это требует во время выполнения накладных расходов на изготовление копии каждого элемента структуры и хранения ее в так называемом стеке (месте, где локальные переменные, используемые в вызове функции, хранятся во время ее выполнения). Когда данные структуры должны быть переданы функции, мы можем использовать указатели на константные данные, чтобы достичь производительности, характерной для передачи по ссылке, и защиты, характерной для передачи по значению. После передачи указателя на структуру должна быть сделана копия только адреса, по которому хранится структура. На машине с 4-байтовыми адресами копию адреса памяти в 4 байта выполнить предпочтительнее, чем копию возможно сотен или тысяч байтов структуры.

ЙЩ Попытка модифицировать данные, переданные посредством неконстантного указателя на константные данные tinclude <iostream.h>

void f(const int *);



mam i {

Hi

int X, y;

int * const ptr = bx; ptr - константный указательна целое.

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

*ptr = 7;

ptr = &у; Ошибка: постоянный объект

модифицировать нельзя.

return 0;

Compiling FIG5 13.CPP:

Error FXG5 13.CPP 14: Cannot modify a const object Warning FXG5 13.CPP 17 : y is declared but never used

Рис. 5.13. Попытка модифицировать константный указатель на неконаантные данные

Наименьший уровень привилегий доступа предоставляет константный указатель на константные данные. Такой указатель всегда указывает на одну и ту же ячейку памяти и данные в этой ячейке нельзя модифицировать. Это выглядит так, как если бы массив нужно было передать функции, которая только просматривает массив, использует его индексы, но не модифицирует сам массив. Программа на рис. 5.14 объявляет переменную указателя ptr типа const int * const. Это объявление читается как ptr является константным указателем на константное целое . На рисунке показаны сообщения об ошибке, генерируемые при попытке модифицировать данные, на которые указывает ptr, и при попытке модифицировать адрес, хранимый в переменной указателе. Заметим, что никакой ошибки не генерируется при попытке вывести значение, на которое указывает ptr, потому что в операторе вывода нет никаких модификаций.

на начало массива. Используя имя массива и индексы массива можно обращаться ко всем данным в массиве и изменять их. Указатели, объявленные как const, должны получить начальные значения при своем объявлении (если указатель является параметром функции, он получает начальное значение, равное указателю, который передается в функцию). Программа на рис. 5.13 пытается модифицировать константный указатель. Указатель ptr объявлен имеющим тип int * const. Это объявление читается как ptr является константным указателем на целое число . Этот указатель получает начальное значение, равное адресу целой переменной х. Программа пытается присвоить ptr адрес у, но это приводит к сообщению об ошибке. Заметим, что ошибки не происходит, когда *ptr присваивается значение 7, - значение, на которое указывает ptr, можно модифицировать.

Типичная ошибка программирования 5.4

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

1 Попытка модифицировать константный указатель на неконстантные данные #include <iostream.h>



Попытка модифицировать константный указатель на константные данные ♦include <iostream.h>

main() {

int X const

= 5, у;

int * const ptr

cout *ptr endl; *ptr = 7; Ошибка: ptr = &y; Ошибка:

return 0;

= &x; ptr - константный указатель на константное целое, ptr всегда указывает на одну и ту же ячейку памяти. Целое нельзя модифицировать

постоянный объект модифицировать нельзя, постоянный объект модифицировать нельзя.

Compiling FIG5 14.CPP:

Error FI65 14.CPP 15: Cannot modify a const object Error FIG5 14.CPP 16: Cannot modify a const object Warning FIG5 13.CPP 19 : y is declared but never used

Рис. 5.14. Попытка модифицировать константный указатель на константные данные

5.6. Пузырьковая сортировка, использующая вызов

по ссылке

Давайте модифицируем программу пузырьковой сортировки на рис. 4.16 так, чтобы использовать две функции - bubbleSort и swap (рис. 5.15). Функция bubbleSort выполняет сортировку массива. Она вызывает функцию swap, чтобы изменить элементы массива аггау[ j ] и array[j -I- 1]. Напомним, что С++ делает взаимноневидимой информацию функций, так что swap не имеет доступа к отдельным элементам массива в bubbleSort. Поскольку bubbleSort хочет, чтобы swap имела доступ к элементам массива и переставляла их, bubbleSort передает функции swap каждый из этих элементов вызовом по ссылке - явно передается адрес каждого элемента массива. Хотя массив в целом автоматически передается вызовом по ссылке, отдельные элементы массива являются скалярными величинами и передаются обычно вызовом по значению. Поэтому bubbleSort использует операцию адресации (&) для каждого элемента массива в вызове swap следующим образом

swap(&агray[j], &array[j+l];

чтобы выполнить вызов по ссылке. Функция swap получает &аггау[ j ] в переменной указателе elementlPtr. Поскольку информация скрыта, swap не может знать имя аггау[ j ], но swap может использовать *elementlPtr как синоним для аггау[ j ]. Таким образом, когда функция swap ссылается на *elementlPtr, она в действительности ссылается на аггау[ j ] в bubbleSort. Аналогичным образом, когда функция swap ссылается на *element2Ptr, она в действительности ссылается на array[j-l-l] в bubbleSort. Несмотря на то, что функция swap не имеет возможности сказать



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

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