Какие идиомы C++ устарели в C++11?
с новым стандартом есть новые способы делать вещи, и многие из них лучше, чем старые способы, но старый способ все еще прекрасен. Также ясно, что новый стандарт официально не очень устарел по причинам обратной совместимости. Так что вопрос остается:
какие старые способы кодирования определенно уступают стилям C++11, и что мы теперь можем сделать вместо этого?
отвечая на это, вы можете пропустить такие очевидные вещи как "авто переменные параметры."
9 ответов:
- Заключительный Класс: C++11 предоставляет
finalспецификатор для предотвращения вывода класса- C++11 лямбды существенно уменьшают потребность в именованных классах объектов функций (функторов).
- Переместить Конструктор: магические способы
std::auto_ptrработы больше не нужны из-за первоклассной поддержки ссылок rvalue.- Safe bool: это было сказано ранее. Явные операторы C++11 устраните эту очень распространенную идиому C++03.
- Shrink-to-fit: многие контейнеры C++11 STL обеспечивают
shrink_to_fit()функция-член, которая должна устранить необходимость замены с временным.- Временный Базовый Класс: некоторые старые библиотеки C++ используют эту довольно сложную идиому. С семантикой перемещения это больше не нужно.
- Введите Безопасное Перечисление перечисления очень безопасны в C++11.
- запрещающие выделение кучи: The
= deleteсинтаксис-это гораздо более прямой способ сказать, что определенная функциональность явно запрещена. Это применимо для предотвращения выделения кучи (т. е.=deleteдля ), предотвращение копирования, присвоения и т. д.- templated typedef:шаблоны псевдоним в C++11 уменьшите потребность в простых шаблонных типах. Однако генераторы сложных типов по-прежнему нуждаются в мета-функциях.
- некоторые численные вычисления времени компиляции, такие как Фибоначчи, могут быть легко заменены с помощью обобщенные константные выражения
result_of: Использование шаблона классаresult_ofследует заменить наdecltype. Я думаюresult_ofиспользуетdecltypeкогда он доступен.- инициализаторы членов класса сохранить ввод для инициализации по умолчанию нестатических элементов со значениями по умолчанию.
- в новом коде C++11
NULLдолжно быть определениеnullptrно вижу стл поговорим чтобы узнать, почему они решили с ним.- Шаблон Выражения фанатики рады трейлинг-тип возвращаемого синтаксис функции в C++11. Не более 30-строчных типов возврата!
я думаю, что остановлюсь на этом!
в какой-то момент времени утверждалось, что нужно вернуться
constзначение вместо просто по значению:const A foo(); ^^^^^это было в основном безвредно в C++98/03, и, возможно, даже поймали несколько ошибок, которые выглядели так:
foo() = a;но, возвращаясь к
constпротивопоказан в C++11, потому что он мешает двигаться семантики:A a = foo(); // foo will copy into a instead of move into itтак что просто расслабьтесь и код:
A foo(); // return by non-const value
как только вы можете отказаться
0иNULLв пользуnullptr, это делать!в неуниверсальный код использования
0илиNULLне такое уж и большое дело. Но как только вы начинаете передавать константы нулевого указателя в общем коде, ситуация быстро меняется. Когда вы проходите0доtemplate<class T> func(T)Tвыводится какintи не как константа нулевого указателя. И после этого он не может быть преобразован обратно в константу нулевого указателя. Это каскады в трясина проблем, которые просто не существуют, если Вселенная используется толькоnullptr.C++11 не осуждает
0иNULLкак константы нулевого указателя. Но вы должны кодировать, как если бы это было так.
Safe bool idiom→
explicit operator bool().частные конструкторы копирования (boost::noncopyable) →
X(const X&) = deleteмоделирование конечного класса с частным деструктором и виртуальным наследованием→
class X final
одна из вещей, которые просто заставляют вас избегать написания основных алгоритмов в C++11, - это доступность лямбд в сочетании с алгоритмами, предоставляемыми стандартной библиотекой.
Я использую их сейчас, и невероятно, как часто вы просто говорите, что хотите сделать, используя count_if (), for_each() или другие алгоритмы вместо того, чтобы снова писать проклятые циклы.
Как только вы используете компилятор C++11 с полной стандартной библиотекой C++11, у вас есть нет хорошего оправдания больше не использовать стандартные алгоритмы для построения вашего. Лямбда просто убей его.
Почему?
на практике (после того, как я сам использовал этот способ написания алгоритмов) гораздо легче читать то, что построено с прямыми словами, означающими то, что сделано, чем с некоторыми циклами, которые вам нужно расшифровать, чтобы узнать смысл. Тем не менее, автоматическое выведение лямбда-аргументов поможет сделать синтаксис более легко сопоставимым с a сырая петля.
в принципе, алгоритмы чтения, выполненные со стандартными алгоритмами, намного проще, поскольку слова скрывают детали реализации циклов.
Я предполагаю, что теперь, когда у нас есть алгоритмы более низкого уровня, нужно думать только о алгоритмах более высокого уровня.
вам нужно будет реализовать пользовательские версии
swapреже. В C++03, эффективный не бросатьswapчасто необходимо избегать дорогостоящих и бросающих копий, а так какstd::swapиспользует двух экземплярах,swapчасто должен быть настроен. В C++,std::swapиспользуетmove, и поэтому фокус смещается на реализацию эффективных и не бросающих конструкторов перемещения и операторов присваивания перемещения. Поскольку для них по умолчанию часто просто отлично, это будет гораздо меньше работы, чем в C++03.как правило, трудно предсказать, какие идиомы будут использоваться, так как они создаются через опыт. Мы можем ожидать "эффективного C++11", возможно, в следующем году, а" стандарты кодирования C++11 " только через три года, потому что необходимого опыта еще нет.
Я не знаю названия для него, но код C++03 часто использовал следующую конструкцию в качестве замены отсутствующего назначения перемещения:
std::map<Big, Bigger> createBigMap(); // returns by value void example () { std::map<Big, Bigger> map; // ... some code using map createBigMap().swap(map); // cheap swap }Это позволило избежать копирования из-за копирования elision в сочетании с
swapвыше.
возврат по значению больше не является проблемой. С семантикой перемещения и / или оптимизацией возвращаемого значения(зависящей от компилятора) функции кодирования более естественны без накладных расходов или затрат(большую часть времени).
когда я заметил, что компилятор, использующий стандарт C++11, больше не ошибается в следующем коде:
std::vector<std::vector<int>> a;для якобы содержащего оператора>>, я начал танцевать. В более ранних версиях нужно было бы сделать
std::vector<std::vector<int> > a;что еще хуже, если вам когда-либо приходилось отлаживать это, вы знаете, насколько ужасны сообщения об ошибках, которые выходят из этого.
Я, однако, не знаю, было ли это "очевидно" для вас.
Comments