Недавно я обнаружил раздражающую проблему в какой-то большой программе, которую я разрабатываю; я хотел бы понять, как исправить это наилучшим образом. Я сократил код до следующего минимального примера.
#include <iostream>
using std::cin;
using std::cout;
class MagicNumbers
{
public:
static const int BIG = 100;
static const int SMALL = 10;
};
int main()
{
int choice;
cout << "How much stuff do you want?\n";
cin >> choice;
int stuff = (choice < 20) ? MagicNumbers::SMALL : MagicNumbers::BIG; // PROBLEM!
cout << "You got " << stuff << "\n";
return 0;
}
Я получаю ошибки ссылок в gcc 4.1.2 при компиляции с -O0 или -O1, но при компиляции с -O2 или -O3 все нормально. Он хорошо связывает использование MS Visual Studio 2005 независимо от параметров оптимизации.
test.cpp:(. text + 0xab): undefined ссылка на `MagicNumbers:: SMALL '
test.cpp:(. text + 0xb3): undefined ссылка на `MagicNumbers:: BIG '
Я посмотрел на код промежуточной сборки, и да, неоптимизированный код рассматривался как SMALL и BIG как внешние переменные int, в то время как оптимизированный использовал фактические числа. Каждое из следующих изменений устраняет проблему:
-
Используйте enum вместо int для констант:
enum {SMALL = 10}
-
Переместите константу (любую) при каждом использовании:
(int)MagicNumbers::SMALL
или(int)MagicNumbers::BIG
или дажеMagicNumbers::SMALL + 0
-
Используйте макрос:
#define SMALL 10
-
Не использовать оператор выбора:
if (choice < 20) stuff = MagicNumbers::SMALL; else stuff = MagicNumbers::BIG;
Мне нравится первый вариант лучше (однако он не идеален, потому что мы фактически используем uint32_t вместо int для этих констант, а перечисление является синонимом int). Но я действительно хочу спросить: чья ошибка?
А я виноват в том, что не понимаю, как работают статические интегральные константы?
Должен ли я обвинять gcc и надеяться на исправление (или, возможно, у последней версии есть исправление, или, может быть, есть неясный аргумент командной строки, чтобы сделать эту работу)?
Между тем, я просто компилирую свой код с оптимизацией, и это боль для отладки: -O3