Скотт Майерс - Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ

Тут можно читать онлайн Скотт Майерс - Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ - бесплатно ознакомительный отрывок. Жанр: comp-programming, издательство Литагент «ДМК»233a80b4-1212-102e-b479-a360f6b39df7, год 2006. Здесь Вы можете читать ознакомительный отрывок из книги онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ
  • Автор:
  • Жанр:
  • Издательство:
    Литагент «ДМК»233a80b4-1212-102e-b479-a360f6b39df7
  • Год:
    2006
  • Город:
    Москва
  • ISBN:
    5-94074-304-8
  • Рейтинг:
    3.6/5. Голосов: 101
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

Скотт Майерс - Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ краткое содержание

Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ - описание и краткое содержание, автор Скотт Майерс, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

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

Издание ориентировано на программистов, знакомых с основами C++ и имеющих навыки его практического применения.

Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ - читать онлайн бесплатно ознакомительный отрывок

Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ - читать книгу онлайн бесплатно (ознакомительный отрывок), автор Скотт Майерс
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

void advance(std::list::iterator& iter, int d)

{

if (typeid(std::iterator_traits::iterator>::iterator_category)==

typeid(std::random_access_iterator_tag))

iter += d; // ошибка!

}

else {

if(d>=0) {while (d–) ++iter;}

else {while(d++) –iter;}

}

}

Проблема в выделенной строке, где встречается оператор +=. В данном случае мы пытаемся использовать += для типа list::iterator, но list::iterator – это двунаправленный итератор (см. правило 47), поэтому он не поддерживает +=. Оператор += поддерживают только итераторы с произвольным доступом. Мы знаем, что никогда не попытаемся исполнить предложение, содержащее +=, потому что для list::iterator проверка с привлечением typeid никогда не выполнится успешно, но компилятор-то обязан гарантировать, что весь исходный код корректен, даже если он никогда не исполняется, а «iter += d» – некорректный код в случае, когда iter не является итератором с произвольным доступом. Решение же на основе технологии TMP предполагает, что код для разных типов вынесен в разные функции, каждая из которых использует только операции, применимые к типам, для которых она написана.

Было доказано, что технология TMP представляет собой полную машину Тьюринга, то есть обладает достаточной мощью для любых вычислений. Используя TMP, вы можете объявлять переменные, выполнять циклы, писать и вызывать функции и т. д. Но такие конструкции выглядят совершенно иначе, чем их аналоги из «нормального» C++. Например, в правиле 47 показано, как в TMP условные предложения if…else выражаются с помощью шаблонов и их специализаций. Но такие конструкции можно назвать «TMP уровня ассемблера». В библиотеках для работы с TMP (например, MPL из Boost – см. правило 55) предлагается более высокоуровневый синтаксис, хотя его также нельзя принять за «нормальный» С++.

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

Аналогом программы «Hello World» на TMP является вычисление факториала во время компиляции. Конечно, она, как и «Hello World», не поразит воображение, но обе полезны для демонстрации базовых возможностей языка. Вычисление факториала с помощью TMP сводится к последовательности рекурсивных конкретизаций шаблона. Кроме того, демонстрируется один из способов создания и использования переменных в TMP. Смотрите:

template // общий случай: значение Factorial – это

struct Factorial { // произведение n и Factorial

enum { value = n*Factorial::value };

};

template<> // частный случай: значение Factorial<0> –

struct Factorial<0> { // это 1

enum { value = 1 };

};

Имея такую шаблонную метапрограмму (на самом деле просто единственную шаблонную метафункцию Factorial), вы получаете значение факториала n, обращаясь к Factorial::value.

Циклическая часть кода возникает там, где конкретизация шаблона Factorial ссылается на конкретизацию шаблона Factorial. Как во всякой рекурсивной программе, здесь есть особый случай, прекращающий рекурсию. В данном случае это специализация шаблона Factorial<0>.

Каждая конкретизация шаблона Factorial является структурой struct, и в каждой структуре используется «трюк с перечислением» (см. правило 2) для объявления переменной TMP с именем value. В переменной value хранится текущее значение факториала. Если бы в TMP были настоящие циклы, то значение value обновлялось бы на каждой итерации цикла. Но поскольку в TMP место циклов заменяет рекурсивная конкретизация шаблонов, то каждая конкретизация получает свою собственную копию value, и значение копии соответствует «итерации цикла».

Использовать Factorial можно следующим образом:

int main()

{

std::cout << Factorial<5>::value; // печатается 120

std::cout << Factorial<10>::value; // печатается 3628800

}

Если вы находите описанный прием элегантным, значит, вы стали на путь превращения в метапрограммиста шаблонов. Если же все эти шаблоны, специализации, рекурсивные конкретизации, трюк с перечислением и необходимость набирать нечто вроде Factorial::value не вызывают у вас восторга, стало быть, вы вполне нормальный программист C++.

Конечно, шаблон Factorial в такой же мере демонстрирует полезность TMP, как «Hello World» – полезность любого обычного языка программирования. Чтобы понять, почему о TMP стоит знать, важно представлять себе, чего можно достичь с помощью этой технологии. Вот три примера:

Обеспечение корректности единиц измерения.В научных и инженерных приложениях важно, чтобы единицы измерения (например, массы, расстояния, времени и т. п.) правильно сочетались. Присваивание переменной, представляющей массу, значения переменной, представляющей скорость, – это ошибка, но деление переменной расстояния на переменную времени и присваивание результата переменной скорости правильно. Используя TMP, можно обеспечить (во время компиляции), что все комбинации единиц измерения в программе будут корректны, независимо от того, насколько сложны вычисления. (Это пример того, как можно использовать TMP для ранней диагностики ошибок.) Одним интересным аспектом такого использования TMP может быть поддержка вычисления дробных степеней. Смысл в том, чтобы дроби сокращались во время компиляции, то есть чтобы компилятор мог подтвердить, например, что единица времени в степени 1/2 – это то же самое, что единица времени в степени 4/8.

Оптимизация операций с матрицами.В правиле 21 объясняется, что некоторые функции, включая operator*, должны возвращать новые объекты, а в правиле 44 представлен класс SquareMatrix, поэтому рассмотрим такой код:

typedef SquareMatrix BigMatrix;

BigMatrix m1, m2, m3, m4, m5; // создать матрицы

... // и присвоить им значения

BigMatrix result = m1 * m2 * m3 * m4 * m5; // вычислить произведение

Вычисление result «нормальным» способом приводит к созданию четырех временных матриц, по одной для каждого вызова operator*. Более того, независимые операции умножения порождают последовательность из четырех циклов по элементам матрицы. Но применение передовой шаблонной технологии, тесно связанной с TMP и получившей название шаблоны выражений (expression templates), позволяет избежать создания временных объектов и объединить циклы, причем все это без изменения приведенного выше пользовательского кода. В результате программа требует меньше памяти и выполняется значительно быстрее.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Скотт Майерс читать все книги автора по порядку

Скотт Майерс - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ отзывы


Отзывы читателей о книге Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ, автор: Скотт Майерс. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x