В общем, вам не хватает того, что путь C часто не быстрее. Это больше похоже на взлом, и люди часто думают, что взломы быстрее.
Никогда не используйте сырые указатели, вместо этого используйте умные указатели - ОК, они действительно полезны, все знают это, я знаю, что я использую все время, и я знаю, насколько они лучше, чем сырые указатели, но иногда это совершенно безопасно использовать сырые указатели .. Почему бы и нет?
Давайте перевернем вопрос с ног на голову. Иногда безопасно использовать сырые указатели. Это одна причина использовать их? Есть ли что-нибудь в необработанных указателях, которые на самом деле превосходят над умными указателями? Это зависит. Некоторые интеллектуальные типы указателей работают медленнее, чем необработанные указатели. Другие нет. Каково обоснование производительности для использования необработанного указателя на std::unique_ptr
или boost::scoped_ptr
? Ни у одного из них нет накладных расходов, они просто обеспечивают более безопасную семантику.
Это не значит, что вы никогда не должны использовать необработанные указатели. Просто вам не следует делать это только потому, что вы думаете, что вам нужна производительность, или просто потому, что «это кажется безопасным». Делайте это, когда вам нужно представить то, что умные указатели не могут. Как правило, используйте указатели, чтобы указывать на вещи, а умные указатели - на владение вещами. Но это правило, а не универсальное правило. Используйте то, что подходит под задачу. Но не думайте вслепую, что сырые указатели будут быстрее. И когда вы используете умные указатели, убедитесь, что вы знакомы со всеми ними. Слишком много людей просто используют shared_ptr
для всего, и это просто ужасно, как с точки зрения производительности, так и с очень расплывчатой семантикой совместного владения, которую вы в итоге применяете ко всему.
Не использовать побитовые операции - слишком в стиле C? WTH? Почему нет, когда ты уверен, что делаешь? Например - не делайте побитовый обмен переменных (a ^ = b; b ^ = a; a ^ = b;) - используйте стандартный трехшаговый обмен. Не используйте сдвиг влево для умножения на два. И т. Д., И т. Д. (ОК, это не стиль C ++ или стиль C, но все же «не очень хорошая практика»)
Это правильно. И причина в том, что «это быстрее». Побитовый обмен проблематичен во многих отношениях:
- медленнее на современном процессоре
- тоньше и проще ошибиться
- работает с очень ограниченным набором типов
А при умножении на два умножить на два . Компилятор знает об этом приеме и применяет его , если он быстрее . И еще раз, у сдвига есть много тех же самых проблем. В этом случае он может быть быстрее (именно поэтому компилятор сделает это за вас), но все же легче ошибиться, и он работает с ограниченным набором типов. В частности, он может хорошо скомпилироваться с типами, которые, как вы думаете, , безопасно сделать с этим трюком ... А потом взорвать на практике. В частности, сдвиг битов на отрицательных значениях - это минное поле. Пусть компилятор найдет его для вас.
Кстати, это не имеет ничего общего с "стилем C". Точно такой же совет применяется в C. В C обычный обмен на все еще быстрее, чем битовый хак, и сдвиг битов вместо умножения будет все еще выполняться компилятором, если он допустимо, и если это быстрее.
Но, как программист, вы должны использовать побитовые операции только для одной цели: делать побитовые манипуляции с целыми числами.У вас уже есть оператор умножения, поэтому используйте , что , когда вы хотите умножить.И у вас также есть функция std::swap
.Используйте это, если вы хотите поменять местами два значения.Одним из наиболее важных приемов оптимизации является, возможно, удивительно, написание читаемого, значимого кода.Это позволяет вашему компилятору понимать код и оптимизировать его.std::swap
может быть специализирован для наиболее эффективного обмена для конкретного типа, на котором он используется.И компилятор знает несколько способов реализации умножения и выберет самый быстрый в зависимости от обстоятельств ... Если вы скажете это.Если вместо этого вы скажете битовому сдвигу, вы просто введете его в заблуждение.Скажите это умножить, и это даст вам самое быстрое умножение, которое у него есть.
И, наконец, самое дорогое: «Не используйте enum-s для возврата кодов, это слишком в стиле C,использовать исключения для разных ошибок "?
Зависит от того, кого вы спрашиваете.Большинство программистов на С ++, которых я знаю, находят место для обоих.Но имейте в виду, что одна из неприятных вещей в кодах возврата заключается в том, что их легко игнорировать.Если это неприемлемо, то, возможно, вам следует предпочесть исключение в этом случае.Другое дело, что RAII лучше работает вместе с исключениями, и программист C ++ должен определенно использовать RAII везде, где это возможно.К сожалению, поскольку конструкторы не могут возвращать коды ошибок, исключения часто являются единственным способом указать ошибки.
, но все же .. Как насчет производительности?
Как насчет этого??Любой приличный программист на Си с радостью скажет вам не оптимизировать преждевременно.
Ваш процессор может выполнять, возможно, 8 миллиардов инструкций в секунду.Если вы сделаете два звонка на std::stringstream
в эту секунду, это изменит существенную величину бюджета?
Вы не можете предсказать производительность.Вы не можете составить руководство по кодированию, которое приведет к быстрому коду.Даже если вы никогда не выбросите ни единого исключения и никогда не будете использовать stringstream
, ваш код все равно не будет работать быстро.Если вы попытаетесь оптимизировать во время написания кода, вы потратите 90% усилий на оптимизацию 90% кода, который вряд ли когда-либо будет выполняться.Чтобы получить ощутимое улучшение, вам нужно сосредоточиться на 10% кода, который составляет 95% времени выполнения.Попытка сделать все быстрым просто приводит к потере большого количества времени, мало чего можно показать, и к более уродливой базе кода.