2010-05-04 6 views
5

У меня очень простой класс, назовите его Basic, который используется почти во всех других файлах в более крупном проекте. В некоторых случаях требуется отладочный вывод, но в режиме выпуска это не должно быть включено и быть NOOP.Производительность C++, оптимизирующий компилятор, пустая функция .cpp

В настоящее время в заголовке есть определение, которое включает или выключает макрос в зависимости от настройки. Так что это определенно NOOP, когда выключен. Мне интересно, если у меня есть следующий код, если компилятор (MSVS/gcc) может оптимизировать вызов функции, так что он снова является NOOP. (Делая это, коммутатор может быть в .cpp, и переключение будет намного быстрее, время компиляции/соединения).

--Header-- 
void printDebug(const Basic* p); 

class Basic { 
    Basic() { 
     simpleSetupCode; 

     // this should be a NOOP in release, 
     // but constructor could be inlined 
     printDebug(this); 
    } 
}; 
--Source-- 
// PRINT_DEBUG defined somewhere else or here 
#if PRINT_DEBUG 
void printDebug(const Basic* p) { 
    // Lengthy debug print 
} 
#else 
void printDebug(const Basic* p) {} 
#endif 

ответ

2

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

+11

Адвокат дьявола: разве это не покрывает большой процент вопросов на этом сайте? Почему люди приходят сюда? Потому что они не знают. И потому, что они либо не знают, как узнать (в этом случае, может быть, они не говорят на сборе), либо они слишком ленивы или поспешили это сделать. Мета-вопрос: мы хотим запретить ленивым/поспешным людям и отвечать только на шланг, который действительно не знает? Некоторые могут быть замешаны в часто задаваемых вопросах (и могут пропустить их); некоторым может понравиться получать пинты снова и снова в основном по одному и тому же вопросу. OP должен был хотя бы обыскать этот сайт (или google), хотя – Mawg

+0

@mawg Он действительно охватывает множество применений этого сайта, и я считаю, что, вероятно, 50% вопросов, заданных здесь, не должны запрашиваться. Этот вопрос, в частности, задается снова и снова, и мой ответ честный - мы не можем сказать, что ваш оптимизатор собирается делать с вашим кодом, только вы можете это сделать. – 2010-05-04 09:00:59

+6

(-1) Итак, ваш ответ не очень «полезен» для пользователя. Вы на самом деле не ответили на их вопросы, независимо от того, был ли это подходящий вопрос или нет. На самом деле, вы не голосовали, чтобы закрыть как дубликат. Если я спрошу «что такое 2 + 2», и вы говорите «выясните это для себя», вы не * помогаете *, и вы не правы *. Это правда, что я должен понять это для себя, но ты не ответил мне. Ваш ответ должен быть комментарием. – DevinB

1

Возможно, компилятор может оптимизировать этот код, если он знает реализацию функции printDebug во время компиляции. Если printDebug находится в другом объектном модуле, возможно, это может быть оптимизировано только компоновщиком, используя всю оптимизацию программы. Но единственный способ проверить это - прочитать код сборки, сгенерированный компилятором. Если у вас уже есть PRINT_DEBUG макрос, вы можете продлить его, кстати, как TRACE определяется:

 
#define PRINT_DEBUG // optional 
#ifdef PRINT_DEBUG 
#define PRINT_DEBUG_CALL(p) printDebug(p) 
#else 
#define PRINT_DEBUG_CALL(p) 
#endif 


void printDebug(const Basic* p); 

class Basic { 
    Basic() { 
     simpleSetupCode; 

     // this should be a NOOP in release, 
     // but constructor could be inlined 
     PRINT_DEBUG_CALL(this); 
    } 
}; 
--Source-- 
// PRINT_DEBUG defined somewhere else or here 
#if PRINT_DEBUG 
void printDebug(const Basic* p) { 
    // Lengthy debug print 
} 
#endif 
+0

Это это именно то, что используется. Но переключение туда и обратно с использованием этого определяет проблемы, которые перекомпилируют проект. – Dodo

+0

Собственно, это не то, что используется, в соответствии с вашим кодом. В моей версии функция printDebug и вызовы к ней не существуют в программе, когда PRINT_DEBUG не определен. О перекомпиляции, да, обе версии требуют перекомпиляции. Но вы не можете ожидать, что компилятор будет оптимизировать пустой вызов функции без перекомпиляции ... –

+0

Прошу прощения, что я не понял. Код, который я написал в вопросе, не является кодом, используемым классом Basic в моем проекте. Тем не менее, код, который вы предоставили, является в основном равным кодом как текущее состояние класса Basic в моем проекте. С кодом, представленным в вопросе, время компиляции и ссылки значительно сокращается по сравнению с версией, которую вы предоставили некоторым другим, при определении/определении флага PRINT_DEBUG. – Dodo

0

errm, почему бы не использовать препроцессор макросов по-разному?

Только в верхней части моей головы, что-то вроде:

#define DEBUG_TRACE(p) 
    #ifdef PRINT_DEBUG 
    printDebug(p); 
    #else 
    ; 
    #endif 
+0

Это не отличается от используемого, написанного иначе. – Dodo

0

В настоящее время большинство оптимизаций выполняются во время компиляции. Некоторые компиляторы, такие как LLVM, могут оптимизировать время ссылки. Это действительно интересная идея. Я предлагаю вам взглянуть.

Ожидая такой оптимизации, вы можете сделать следующее. Определите макрос, который позволяет включать следующий оператор в зависимости от того, определен ли DEBUG или нет.

#ifdef DEBUG 
#define IF_DEBUG (false) {} else 
#else 
#define IF_DEBUG 
#endif 

чем вы можете использовать его как это

Basic() { 
     simpleSetupCode; 

     // this should be a NOOP in release, 
     // but constructor could be inlined 
     IF_DEBUG printDebug(this); 
    } 

, которая уже гораздо более читабельным, чем

Basic() { 
     simpleSetupCode; 

     // this should be a NOOP in release, 
     // but constructor could be inlined 
#if DEBUG 
     printDebug(this); 
#endif 
    } 

Обратите внимание, что вы можете использовать его, как если бы это было ключевое слово

IF_DEBUG { 
    printDebug(this); 
    printDebug(thas); 
} 
1
#if PRINT_DEBUG 
#define printDebug _real_print_debug 
#else 
#define printDebug(...) 
#endif 

Таким образом препроцессор будет деактивировать весь отладочный код, прежде чем он даже попадет в компилятор.

Смежные вопросы