Есть ли какая-либо разница между вычислением выражений между двумя приведенными ниже операторами возврата на основе дополнительных скобок?
blockquote>Нет; круглые скобки полностью излишни в этом случае .
Выражение
expr
на самом деле не совпадает с выражением(expr)
, и вы можете наблюдать это с помощьюreturn
, потому что исключение копирования / перемещения запрещено в последнем случае:#include
struct T { T() { std::cout << "T()\n"; } T(const T&) { std::cout << "T(const T&)\n"; } T(T&&) { std::cout << "T(T&&)\n"; } ~T() { std::cout << "~T()\n"; } }; T foo() { T t; return t; } T bar() { T t; return (t); } int main() { std::cout << "Test 1\n------\n"; foo(); std::cout << '\n'; std::cout << "Test 2\n------\n"; bar(); } Вывод:
Test 1 ------ T() ~T() Test 2 ------ T() T(T&&) ~T() ~T()
( live demo )
Вероятно, вы можете наблюдать тот же результат до C ++ 17, потому что компиляторы всегда пытались оптимизировать возврат ценности. Даже в вашем стандарте C ++ 98 вы, вероятно, можете заметить, что конструктор копирования не вызывается в первом случае.
Но, эй, ничего из этого не имеет отношения к простому арифметическому выражению.
Можно сделать точные измерения путем чтения счетчика метки времени (tsc) ЦП, который увеличен одним в каждом тактовом CPU.
К сожалению, чтение сделано, встроив некоторые ассемблерные инструкции в коде. В зависимости от базовой архитектуры стоимость чтения варьируется между ~11 (AMD) и ~33 (Intel) tsc. С 1 ГГц ЦП у Вас может фактически быть точность наносекунды.
Для выполнения надежной и неразрушающей меры раздела кода, Вы можете:
Здесь можно найти квазипортативный класс C++, который я записал для Linux, полученного из ядра Linux, и разработал для чтения tsc для архитектуры i386, x86_64 и ia64.
Если Вы - код времени, стоит выполнить его много времен в цикле для предотвращения эффекта разрешения таймера. Таким образом, Вы могли бы выполнить вещь, которую Вы синхронизируете 10,000 раз и измеряете количество времени, которое она занимает для выполнения всех повторений. Вероятно, только потребуется несколько секунд для выполнения, и Вы получите лучшие данные синхронизации.
Используя "количество операций" плохая идея при размышлении о производительности. Это не принимает во внимание различия между лучшим случаем / худшими счетами цикла случая для каждой операции, затрат на неудачные обращения в кэш, конвейер промахи, потенциальное (автоматическое) распараллеливание и т.д.
Как Greg говорит, обычно это - лучшая идея для микросравнительного теста, чтобы просто выполнить тот же код достаточно раз для получения достойного промежутка времени.
Еще лучше должен запустить Ваше целое приложение с реалистической рабочей нагрузкой и измерить метрики, которыми Вы действительно интересуетесь, но это - другой разговор...
То, что, конечно, полезно, должно решить, что сложность Вашего кода - знает, когда метод будет O (1), O (зарегистрируйте n), O (n) и т.д. Это обычно не включает знание деталей того, что отдельные инструкции в C++ делают - хотя действительно необходимо знать сложность чего-либо, что Вы называете. (История Joel Shlemiel Живописец и strlen быть самым очевидным примером.)
Демонстрационный профилировщик является хорошим выбором здесь. В Windows можно использовать профилировщика, встроенного в Visual Studio или xperf инструменты от организации Windows. xperf инструменты являются бесплатными. Вот ряд сообщений на xperf инструментах от меня. Этот о профилировании.
Генерируйте операции количества и блок. Затем рассмотрите cycles/op, который использует Ваш процессор. Затем помните, что Вы работаете над приоритетной ОС, и ничего подобного не допустим.
Более серьезно поднимите свой n и масштабируйте свою программу к непристойным размерам. Это даст Вам общее представление о том, какова Ваша скорость программы.
Почему Вы только не выполняете свой код при профилировщике? Это обычно дает Вам данные о том, сколько времени проведено в функциях, а также сколько раз их называют.
Знание, сколько раз вызвана функция, полезно, потому что это может позволить Вам определять потенциальные проблемы производительности, если функция вызывается намного чаще, чем Вы чувствуете, что это должно быть.
Конечно, использование профилировщика делает Ваш код медленнее, но это неизбежно при добавлении любого вида инструментария.
Если Вы обеспокоены тем, чтобы заставлять Вашу программу пойти максимально быстро, и это - единственный поток, и Вы используете IDE, проверяете это: Как Оптимизировать Производительность Вашей Программы
Используйте valgrind на Linux. Это имеет синхронизацию уровня инструкции, включая анализ кэша.
Если Вы хотите точную синхронизацию (на окнах), не используя профилировщика, можно взглянуть на этот поток, который представляет различные способы представить код C++.
Если Вы хотите фактическое операционное прибытие количеств из своих аппаратных средств, то можно хотеть рассмотреть установку пакета как PAPI - Производительность API - который работает через многих другая ОС и комбинации процессора. Это использует фактические аппаратные счетчики и сообщает или о прямых или полученных значениях для большого количества различных метрик производительности, таких как Общая операция в секунду, флопс, хиты/промахи кэша, и т.д. Это может также предоставить доступ к более высоким таймерам разрешения.
Это не самый легкий пакет никогда, но уровень создания отчетов может действительно помочь Вам проанализировать поведение своего приложения на Ваших аппаратных средствах.