У меня есть пример кода, где прямая оптимизация не работает, когда структурирована как переменные класса, но работает как локальные переменные; Я хочу знать: почему не происходит оптимизация формулировки переменных класса?
Цель моего примера кода состоит в том, чтобы иметь класс, который либо включается, либо отключается при создании и, возможно, изменяется в течение его жизни. Я ожидаю, что когда объект отключен на все время его жизни, компилятор оптимизирует весь код, который условно выполняется, когда объект включен.
В частности, у меня есть std::ofstream, в который я хочу писать только тогда, когда он «включен». Когда отключено, я хочу, чтобы весь форматированный вывод был пропущен. (Мой реальный класс выполняет собственное нетривиальное форматирование сообщений.)
Я обнаружил, что когда я формулирую это как класс, я не получаю ожидаемой оптимизации. Однако, если я воспроизведу весь код как локальные переменные, я увижу ожидаемое поведение.
Кроме того, я обнаружил, что если я не делаю вызовы std::ofstream, такие как «open», «exceptions» или «clear» в теле методов класса-примера, я также получаю ожидаемые оптимизации. (Однако мой дизайн требует выполнения таких вызовов std::ofstream, поэтому для меня это спорный вопрос.) В приведенном ниже коде используется MACRO DISABLE_OPEN_OFSTREAM_AFTER_CONSTRUCTOR, позволяющий попробовать этот случай.
В моем примере кода используются выражения asm для вставки комментариев в сгенерированный ассемблерный код. Если кто-то проверит вывод компилятора в сборке, я ожидаю, что между комментариями «disabled-test» сборки не будет. Я наблюдаю сборку между комментариями «class disabled-test», но не сборку между комментариями «locals disabled-test».
Входной код С++:
#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. Однако это кажется такой простой оптимизацией, что мне трудно поверить, что это может быть ошибка компилятора.
Любая помощь, понимание или руководство приветствуется.