У меня есть пример кода, где прямая оптимизация не работает, когда она структурирована как переменные класса, но работает как локальные переменные;Я хочу знать: почему оптимизация не происходит при формулировке переменных класса?
Цель моего примера кода состоит в том, чтобы иметь класс, который либо включается, либо отключается при построении и, возможно, изменяется во время его существования.Я ожидаю, что, когда объект отключен в течение всего его времени жизни, компилятор оптимизирует весь код, который условно выполняется, когда объект включен.
В частности, у меня есть std :: ofstream, который я хочу тольконаписать, когда "включен".Когда отключено, я хочу, чтобы весь форматированный вывод был пропущен.(Мой реальный класс выполняет свое нетривиальное форматирование сообщений.)
Я обнаружил, что когда я формулирую это как класс, я не получаю ожидаемых оптимизаций.Однако, если я реплицирую код все как локальные переменные, я вижу ожидаемое поведение.
Кроме того, я обнаружил, что если я не выполняю вызовы std :: ofstream, такие как «open», «exception»,или 'очистить' где-нибудь в теле методов класса примера, я также получаю ожидаемые оптимизации.(Тем не менее, мой дизайн требует выполнения таких вызовов на std :: ofstream, поэтому для меня это спорный вопрос.) В приведенном ниже коде используется MACRO DISABLE_OPEN_OFSTREAM_AFTER_CONSTRUCTOR, чтобы разрешить один попробовать этот случай.
Мой пример кода использует 'выражения asm для вставки комментариев в сгенерированный ассемблерный код.Если кто-то проверяет вывод компилятора в сборке, я ожидаю, что между комментариями 'disabled-test' сборки не будет.Я наблюдаю сборку между комментариями «класса отключенного теста», но пока нет сборки между комментариями «локального отключения теста».
Входной код C ++:
#include <fstream> // ofstream
#define DISABLE_OPEN_OFSTREAM_AFTER_CONSTRUCTOR 0
class Test_Ofstream
{
public:
Test_Ofstream( const char a_filename[],
bool a_b_enabled )
#if DISABLE_OPEN_OFSTREAM_AFTER_CONSTRUCTOR
: m_ofstream( a_filename ),
m_b_enabled( a_b_enabled )
{
}
#else
: m_ofstream(),
m_b_enabled( a_b_enabled )
{
m_ofstream.open( a_filename );
}
#endif
void write_test()
{
if( m_b_enabled )
{
m_ofstream << "Some text.\n";
}
}
private:
std::ofstream m_ofstream;
bool m_b_enabled;
};
int main( int argc, char* argv[] )
{
{
Test_Ofstream test_ofstream( "test.txt", true );
asm( "# BEGIN class enabled-test" );
test_ofstream.write_test();
asm( "# END class enabled-test" );
}
{
Test_Ofstream test_ofstream( "test.txt", false );
asm( "# BEGIN class disabled-test" );
test_ofstream.write_test();
asm( "# END class disabled-test" );
}
{
bool b_enabled = true;
#if DISABLE_OPEN_OFSTREAM_AFTER_CONSTRUCTOR
std::ofstream test_ofstream( "test.txt" );
#else
std::ofstream test_ofstream;
test_ofstream.open( "test.txt" );
#endif
asm( "# BEGIN locals enabled-test" );
if( b_enabled )
{
test_ofstream << "Some text.\n";
}
asm( "# END locals enabled-test" );
}
{
bool b_enabled = false;
#if DISABLE_OPEN_OFSTREAM_AFTER_CONSTRUCTOR
std::ofstream test_ofstream( "test.txt" );
#else
std::ofstream test_ofstream;
test_ofstream.open( "test.txt" );
#endif
asm( "# BEGIN locals disabled-test" );
if( b_enabled )
{
test_ofstream << "Some text.\n";
}
asm( "# END locals disabled-test" );
}
return 0;
}
Выходные данныекод сборки:
##### Cut here. #####
#APP
# 53 "test_ofstream_optimization.cpp" 1
# BEGIN class disabled-test
# 0 "" 2
#NO_APP
cmpb $0, 596(%esp)
je .L22
movl $.LC1, 4(%esp)
movl %ebx, (%esp)
.LEHB9:
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
.LEHE9:
.L22:
#APP
# 55 "test_ofstream_optimization.cpp" 1
# END class disabled-test
# 0 "" 2
#NO_APP
##### Cut here. #####
#APP
# 116 "test_ofstream_optimization.cpp" 1
# BEGIN locals disabled-test
# 0 "" 2
# 121 "test_ofstream_optimization.cpp" 1
# END locals disabled-test
# 0 "" 2
#NO_APP
##### Cut here. #####
Я понимаю, что это, возможно, связано с компилятором, который я использую: g ++ - 4.6 (Debian 4.6.1-4) 4.6.1;флаги компилятора: -Wall -S -O2.Тем не менее, это кажется такой простой оптимизацией, что мне трудно поверить, что это может привести к поломке компилятора.
Любая помощь, понимание или руководство очень приветствуются.