Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Средства C, которых рекомендуется избегатьСодержание книги
Поиск на нашем сайте
По замечанию Страуструпа, «чем лучше вы знаете C, тем труднее вам будет избежать программирования на C++ в стиле C, теряя при этом потенциальные преимущества C++». В связи с этим он даёт следующий набор рекомендаций для программистов на C, чтобы в полной мере воспользоваться преимуществами C++:
Дальнейшее развитие Текущий стандарт языка ISO/IEC 14882:2003(E) был принят в 2003 году. Неофициально его обозначают как C++03. Следующая версия стандарта, опубликованная 1 сентября 2011 года, имеет неофициальное обозначение C++11. Общие направления развития C++ По мнению автора языка Бьёрна Страуструпа[11][12][13], говоря о дальнейшем развитии и перспективах языка, можно выделить следующее:
Стандарт C++11: дополнения в ядре языка Явно определяемые константные функции и выражения constexpr. В язык вводится ключевое слово constexpr, которым может быть помечено объявление функции, если она возвращает константу времени компиляции, или константной переменной, которая инициализируется выражением, содержащим только константы времени компиляции. Константные выражения могут использоваться везде, где по семантике программы требуется константа времени компиляции, например — в инициализаторах статических объектов. Предполагается, что константные выражения позволят программисту проще и точнее описывать семантику программы, а компилятору — шире применять предвычисление выражений на этапе трансляции кода. Универсальная инициализация. Инициализация массивов и объектов списками константных значений, заключёнными в фигурные скобки. Значительно упростит инициализацию сложных объектов. Конструкторы и операторы присваивания с семантикой переноса. Отдельное описание для конструкторов и присваиваний, реализующих перенос значения из источника в приёмник (то есть не гарантирующих сохранность объекта-источника после завершения операции). Во многих случаях такие конструкторы и присваивания могут быть описаны значительно более эффективно, чем обычные копирующие конструкторы и полноценные присваивания. Наличие их позволяет компилятору использовать эти более эффективные описания при работе с временными объектами (представляющими результаты выражений, аргументы или возвращаемые значения функций) что, в итоге, увеличивает производительность программ, работающих со сложными объектами. Конструкторы и операторы преобразования типов — новые возможности. Разрешён прямой вызов одного конструктора из другого, что уменьшает дублирование кода и исключает необходимость создания скрытых методов-инициализаторов. Для операторов преобразования типов разрешено описание с ключевым словом explicit — запрет на неявное преобразование типа параметра при вызове. Вывод типов. Для применения в шаблонах, там, где затруднительно указать конкретный тип переменной, введены два новых механизма: переменные типа auto и описание decltype. Оба используются на месте типа переменной при её объявлении. Переменная типа auto должна быть явно инициализирована некоторым выражением и её тип компилятор определяет по типу значения выражения-инициализатора. Соответственно, если в инициализации участвуют значения шаблонных типов или вызовы шаблонных функций, тип переменной определяется с учётом конкретных подставленных типов-параметров этих шаблонов. Описание вида «decltype(x) y» понимается как «y имеет тип выражения x», то есть компилятор выводит тип выражения x и определяет y как переменную этого типа. Все эти операции производятся только на этапе компиляции, то есть статическая типизация не нарушается. Чтобы обеспечить возможность указывать через decltype тип возвращаемого значения функции, когда он зависит от типов параметров, введён альтернативный синтаксис объявления функции: auto func(params) -> type соответствует type func(params). Например, auto f(T x, T y) -> decltype(x+y) определяет функцию f как возвращающую тип, выводимый из выражения «x+y»[пояснения 1] Цикл по коллекции. Вслед за многими современными языками в C++ введена конструкция «цикл по коллекции» вида for(type &x: array){...}. Здесь тело цикла выполняется для каждого элемента коллекции array, а x в каждой итерации будет ссылаться на очередной элемент коллекции. В качестве коллекции может выступать C-массив или любой контейнер стандартной библиотеки, для которого определены итераторы begin и end. Лямбда-выражения. Добавлена возможность объявлять лямбда-выражения (безымянные функции, определяемые в точке применения), в том числе зависящие от внешних переменных (замыкания). Лямбда-выражения могут присваиваться переменным и использоваться везде, где требуется функция соответствующего типа, например, в алгоритмах стандартной библиотеки. Изменения в описании виртуальных методов. Добавлен необязательный модификатор override, который употребляется в объявлении метода, замещающего виртуальный метод родительского класса. Описание замещения с override вызывает проверку на наличие в родительском классе замещаемого метода и на совпадение сигнатур методов. Добавлен также модификатор final, как и в Java, запрещающий дальнейшее замещение помеченного им метода. Также final может быть объявлен класс — в таком случае от него запрещено наследовать новые классы. Изменения в механизме шаблонов. Добавлена возможность описания шаблонов с неопределённым числом параметров и возможность объявления синонимов для неспециализированных или частично специализированных шаблонов. Ключевое слово export при объявлении специализации шаблона указывает компилятору на то, что фактически специализация сделана в другой единице компиляции, что позволяет избежать повторной специализации одних и тех же шаблонов одними и теми же параметрами. Различные синтаксические дополнения. Определено ключевое слово для константы — нулевого указателя: nullptr. Его использование позволяет избежать путаницы между целым нулевым значением и пустым указателем, которая возникает при использовании константы 0, как требовалось ранее. Внесены изменения в семантику и, частично, синтаксис перечислений и объединений. Добавлена возможность создавать типобезопасные перечисления, с объединений снят ряд ограничений на структуру. От компилятора требуется правильный лексический разбор текста программы с несколькими закрывающимися угловыми скобками подряд (ранее последовательность «>>» воспринималась однозначно как операция вывода в поток, поэтому в записи вложенных шаблонных конструкций требовалось обязательно разделять знаки «больше» пробелами или переводами строк). sizeof теперь может возвращать размер члена класса по его имени, без указания конкретного экземпляра (sizeof(ClassA::b)). Стандарт C++11: изменения в стандартной библиотеке
Проблемные моменты Одним из камней преткновения стало ключевое слово export в шаблонах, где оно используется для разделения объявления и определения спецификации шаблона (нововведение стандарта «C++98»). Герб Саттер, секретарь комитета по стандартизации C++, рекомендовал убрать export из будущих версий стандарта по причине серьёзных сложностей в полноценной реализации, однако впоследствии его решили оставить. Первым компилятором, поддерживающим export в шаблонах, стал Comeau C++ в начале 2003 года (спустя 5 лет после выхода стандарта C++98). В 2004 году бета-версия компилятора Borland C++ Builder X также начала его поддержку. Оба этих компилятора основаны на фронт-энде EDG. Другие компиляторы, такие как Microsoft Visual C++ или GCC (до версии 3.4.4), вообще этого не поддерживают. Поддерживают export: Microsoft Visual C++ 7.0, GCC 3.4.4, Microsoft Visual Studio 2010 и другие. Из списка других проблем, связанных с шаблонами, можно привести вопросы конструкций частичной специализации шаблонов, которые плохо поддерживались в течение многих лет после выхода стандарта C++. Примеры программ Пример создания простой программы на языке C++ в Ubuntu GNU/Linux Пример № 1 Это пример программы, которая ничего не делает. Она начинает выполняться и немедленно завершается. Она состоит из основного потока: функции main(), которая обозначает точку начала выполнения программы на C++. int main() { return 0; } Стандарт C++ требует, чтобы функция main() возвращала тип int. Программа, которая имеет другой тип возвращаемого значения функции main(), не соответствует стандарту C++. Стандарт не говорит о том, что на самом деле означает возвращаемое значение функции main(). Традиционно оно интерпретируется как код возврата программы. Стандарт гарантирует, что возвращение 0 из функции main() показывает, что программа была завершена успешно. Завершение программы на C++ с ошибкой традиционно обозначается путём возврата ненулевого значения. Пример № 2 Эта программа также ничего не делает, но более лаконична. int main(){} В C++ (как и в C), если выполнение программы доходит до конца функции main(), то это эквивалентно return 0;. Это неверно для любой другой функции кроме main(). Пример № 3 Это пример программы Hello, world!, которая выводит сообщение, используя стандартную библиотеку, и завершается. // это подключает заголовочный файл iostream #include <iostream>
using namespace std;
int main() { cout << "Hello, world!" << endl; // можно и "...\n" вместо endl return 0; } Пример № 4 Современный C++ позволяет решать простым способом и более сложные задачи. Этот пример демонстрирует кроме всего прочего использование контейнеров стандартной библиотеки шаблонов (STL). #include <iostream> // для использования std::cout #include <vector> // для std::vector<> #include <map> // для std::map<> и std::pair<> #include <algorithm> // для std::for_each() #include <string> // для std::string
using namespace std; // используем пространство имён "std"
void display_item_count(pair < string const, vector<string> > const& person) { // person - это пара двух объектов: person.first - это его имя, // person.second - это список его предметов (вектор строк) cout << person.first << " is carrying " << person.second.size() << " items" << endl; }
int main() { // Объявляем карту со строковыми ключами и данными в виде векторов строк map< string, vector<string> > items;
// Добавим в эту карту пару человек и дадим им несколько предметов items["Anya"].push_back("scarf"); items["Dmitry"].push_back("tickets"); items["Anya"].push_back("puppy");
// Переберём все объекты в контейнере for_each(items.begin(), items.end(), display_item_count); } В этом примере для простоты используется директива использования пространства имён, в настоящей же программе обычно рекомендуется использовать объявления, которые аккуратнее директив: #include <vector>
int main() { using std::vector;
vector<int> my_vector; } Здесь директива помещена в область функции, что уменьшает шансы столкновений имён (это и стало причиной введения в язык пространств имён). Использование объявлений, сливающих разные пространства имён в одно, разрушает саму концепцию пространства имён.[ источник не указан 1291 день ] Пример № 5 Популярные библиотеки boost в сочетании со стандартными средствами языка позволяют очень лаконично и наглядно записывать код. В приведённом ниже примере вычисляется скалярное произведение векторов нечётных чисел и квадратов. В коде вектора значений представлены ленивыми STL-подобными последовательностями. #include <iostream> #include <numeric> #include <boost/iterator/counting_iterator.hpp> #include <boost/iterator/transform_iterator.hpp>
int odd(int i) { return 2 * i + 1; }
int square(int i) { return i * i; }
typedef boost::counting_iterator <int> counter; typedef boost::transform_iterator <int (*)(int), counter> transformer;
transformer odds(int n) { return transformer(counter(n), odd); }
transformer squares(int n) { return transformer(counter(n), square); }
int main() { using namespace std;
cout << "Enter vector length: "; int n; cin >> n;
cout << inner_product(odds(0), odds(n), squares(0), 0) << endl; } Данный пример демонстрирует так называемый «плоский» стиль записи. Это название связано с тем, что алгоритмы STL позволяют записывать код без циклов, соответственно ширина отступов в отформатированном коде примерно постоянна. Сторонники такого подхода считают, что программисту, знакомому со стандартной библиотекой С++, достаточно строчки с вызовом inner_product(), чтобы понять, что делает программа. С этой точки зрения вызов inner_product близок к словесному описанию задачи: «вычислить скалярное произведение векторов нечётных чисел и квадратов для значений от нуля до n».
|
||||
Последнее изменение этой страницы: 2016-12-12; просмотров: 179; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.14.143.149 (0.013 с.) |