Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 [ 58 ] 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

auto в качестве ключевого слова для автоматического выведения типа, так что в будущем, быть может, мы будем заменять объявления наподобие

vector<SomeNamepace: •.SomeType>: .const i terator i = v.begino ;

простым и выразительным

auto i = v.begino; Возможное будущее расширение С++

register

Но достаточно об auto. Обратимся к register. 3. Как добавление ключевого слова register изменяет семантику программы на С++?

Говоря коротко: для большинства современных компиляторов - никак.

Чтобы понять, почему - посмотрим, что говорит стандарт сразу после процитированного примечания об auto... Начинается он так:

Спецификатор register имеет ту же семантику, что и спецификатор auto...

Гм... Как мы только что выяснили, это означает "не имеет семантики". Грустное начало... Но прочтем дальше:

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

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

и в большинстве реализаций она будет проигнорирована, если запрашивается адрес

объекта.] - [C++03J §7.1.1

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

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

> рекомендация

Никогда не используйте ключевое слово register, кроме тех случаев, когда вы досконально знаете компилятор и особенности применения в нем этого спецификатора. Для большинства компиляторов это ключевое слово означает то же, что и пробельный символ.

Резюме

Итак, вы уже знаете, почему С++ резервирует ключевые слова, и выяснили, что два из них - auto и regi ster - не привносят никаких семантических изменений в программу на С+ + . Не используйте их - по сути это всего лишь разновидность



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

Никогда НС пишите в программе auto. Это ключевое слово не имеет никакого значения.

Никогда не пишите в программе register (если только у вас нет абсолютной уверенности в том, что это слово имеет значение при использовании вашего компилятора в конкретном исходном тексте). Для большинства компиляторов этот спецификатор ничем не отличается от пробельного символа.



Задача 29. Инициализация ли это? Сложность: 3

в этой задаче мы рассмотрим такой вопрос: "Что если мы инициализировали объект, и ничего не произошло?"

В задаче предполагается, что все соответствующие стандартные заголовочные файлы включены и сделаны все необходимые usi пд-объявления.

Вопрос для новичка

1. Что делает следующий исходный текст?

deque<string> colli;

copyCistream iterator<string>( cin ),

i streanui terator<stri ng>0 ,

back inserter( colli ) );

Вопрос для профессионала

2. Что делает следующий исходный текст?

deque<string> со112( col 11.begiп(), colli.end() ); deque<string> coll3( istream Tterator<string>( cin ), istream iterator<string>0 );

3. Что следует изменить в программе, чтобы она работала так, как, вероятно, ожидает программист?

Решение

Базовый механизм заполнения

1. Что делает следующий исходный текст?

пример 29 1(a)

deque<string> colli;

copy(istream iterator<string>( ci n ),

istreanuiterator <stri ng>0 ,

back inserter( col 11 ) );

В приведенном фрагменте объявляется изначально пустой дек строк с именем colli. Затем выполняется заполнение путе.м копирования строк, разделенных пробельными символами, из стандартного потока ввода ci п в дек с использованием функции deque: :push back, пока не закончится весь входной поток.

Исходный текст примера 29-1(a) эквивалентен следующему.

пример 29-1(6): Эквивалентная запись 29-1(а)

deque<string> colli;

istream„iterator<strinq> fi rst( cin ), last; copy( first, last, back inserter( col 11 ) );

Единственное отличие от исходного текста 29-1(a) состоит в том, что в нем обьекты istream iterator создавались "на лету", как временные неименованные, так что они уничтожались по завершении вызова сору. В примере 29-1(6) объекты i s-tream iterator являются именованными переменными и благополучно "переживают" вызов сору, они не будут уничтожены до тех пор, пока не будет достигнут конец области действия, в которой находится исходный текст примера 29-1(6).



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 [ 58 ] 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85