Посоветуйте книгу по С++

Изображение пользователя nitrofox.

Хотелось почитать подробнее о нововведениях С++14. Ну и добавить хорошую книгу в свою коллекцию книг.
Я ради интереса написал функцию auto max(auto a, decltype(a) b); И она работает. Но я не могу найти в каком стандарте добавили возможность использовать auto к аргументам функции. Да и само поведение чуток непонятное.

0
MacLeod - 26 Февраль, 2016 - 10:16
Изображение пользователя MacLeod.

Ржунимагу. Такой ад никогда и не планировался даже. Это же делает невозможной перегрузку функций. Были планы позволить использование auto максимум в лямбдах в 14-том стандарте.
Visual Studio 2015 еще до компиляции говорит:

и

Пояснение по компилятору: https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(C3533)&rd=true.

Попробуйте скормить это шлангу (clang) - он вам тоже разъяснит что почем. Не знаю, что курили разрабы GCC.

Что до книг... Последние изменения не тянут на книгу, вполне достаточно пробежаться по статьям, а при очень жгучем желании - можно вчитаться в сам драфт.
Да и еще ни одна книга чисто по языку не делала из человека программиста. Но на эти грабли наступает большинство.
Очень рекомендую к ознакомлению дисциплину "алгоритмы и структуры данных". Умение вычислять ассимптотическую сложность (O(1), O(log(N)), O(N), O(N*N) и т.д.) позволяет не только повысить эффективность, но и вообще делает возможной реализацию некоторых вещей при современных объемах данных. Хранение данных - это вообще вопрос на миллион. Типовые контейнеры и собственные структуры должны подбираться исходя из задачи (объема данных, соотношения количества операций чтения/вставки/удаления). Например, базовые контейнеры STL/Boost не всегда эффективны, поскольку это универсальные решения. Но и для максимально эффективного их использования желательно хотя бы попробовать самостоятельно реализовать каждый из них.
Если вернуться к с/с++, то как бы туда не прикручивали новомодных штуковин - по подобным фичам он всегда будет отставать от более молодых решений. Но у него есть один очень весомый плюс, который в контексте человеческого фактора (при недостаточном понимании) также часто является минусом - ручное управление выделением памяти. При малых объемах данных он позволяет ограничиться стеком, при больших - выделить в куче нужный объем на начальном этапе и не дергать ее лишний раз в основном цикле. Любое выделение памяти в куче - обращение к ОС, что тащит за собой тьму операций и автоматом увеличивает алгоритмическую сложность программы. Еще, к примеру, казалось бы, двусвязный список хорошо подходит для вставки элементов в середину, быстрого удаления из любого места и вставки в любое место (ну, как бы, значения указателей-то поменять, по сути O(1)). Как и быстрое последовательное чтение элементов в обе стороны. Но не все так просто с точки зрения управления памятью: вставка нового элемента - это выделение на куче (тьма операций), удаление элемента - освобождение кусочка кучи (может привести к реаллокации памяти ОСью), а последовательное чтение на самом деле - дико медленное, поскольку данные в памяти у двусвязного списка лежат не последовательно, а в разных местах, в итоге - много операций обращения к оперативке и кэш-миссы процессора.
На плюсы лучше смотреть именно с этой позиции. Какими бы красивыми конструкциями и паттернами все не описывалось - не стоит забывать, что в итоге это все будет выполняться железкой, архитектура которой меняться точно не спешит.
Ну и, ИМХО, это все дико интересно, особенно поначалу.
Что-то опять много букв получилось...)

0
nitrofox - 26 Февраль, 2016 - 17:35
Изображение пользователя nitrofox.

Ну я думал что это эквивалент
auto max(auto a, decltype(a) b) { return a > b ? a : b;}
template <typename T> T min(T a, T b) { return a < b ? a : b; }

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

И правда Clang ругается =)

Я читал книгу(вроде Страуструп), там очень подробно рассказывалось о векторах ,списках, деревьях... Для примера там объяснялось как самому реализовать эти классы. +На ютубе смотрел пару лекций на эту тему(в них рассказывалось о структурах данных, о проблемах производительности). Так что примерно понимаю как контейнеры хранят данные и какие затраты требуются для разных манипуляций. Мне не книгу о нововведениях С++14, а хороший справочник о С++(03, 11, 14) хотелось бы=)На случай если гугл сломается или горячий чай поставить нужно.

0
MacLeod - 26 Февраль, 2016 - 17:55
Изображение пользователя MacLeod.

Ну, auto идентифицирует типы по методу шаблонов, decltype - видимо, по-другому.
Если шаблон очевиден и предсказуем, как реализована обработка такой конструкции в gcc - я не знаю, и не совсем понимаю, зачем путать код подобными вещами.

Про структуры - смотреть это одно, а попробовать реализовать, загнать в него пару-тройку гигов и погонять на скорость, сравнивая по производительности с тем же STL =) На частных случаях, если писать индивидуальный контейнер - можно получить прирост в два порядка.

По справочнику - не знаю даже, по необходимости MSDN смотрю, http://clang.llvm.org/docs/, а вообще - справочники обычно требуются по фреймворку какому или SDK.

0
Гость - 27 Февраль, 2016 - 05:42

Ну, совершенно логично, что конструкция типа "auto a", как определение аргумента функции, не будет работать. Это вообще не имеет смысла, ведь auto - это не просто замена описания конструкции шаблона. auto - это просто способ сократить код, оно позволяет определить тип переменно на основании возвращаемого (если функция)/инициализирующего типа данных. Т.е. компилятор, пробегая по коду, анализирует тип инициализирующего значения и присваивает переменной этот тип. А если auto в описании аргументов функции, то как компилятор может понять, какие именно в дальнейшем типы вы подсунете в качестве аргумента функции?
Например, в коде:
auto foo(){
   return 3.14;
}

компилятор однозначно определит типа возвращаемого значения функции, как double.

0
MacLeod - 27 Февраль, 2016 - 14:43
Изображение пользователя MacLeod.

А если auto в описании аргументов функции, то как компилятор может понять, какие именно в дальнейшем типы вы подсунете в качестве аргумента функции?
Обсуждение этого момента и возникло по причине, что пример товарища nitrofox - собирается и работает при использовании gcc 5.2.1. Предположительно, создаются копии функций для всех наборов аргументов, как при использовании темплейтов. Другой вопрос - зачем. И задавать его стоит разработчикам gcc.

Отправить комментарий

CAPTCHA на основе изображений
Введите цифры