Я недавно обнаружил раздражающую проблему в какой-то большой программе, которую я разрабатываю;Я хотел бы понять, как это исправить наилучшим образом.Я сократил код до следующего минимального примера.
#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): неопределенная ссылка на тест MagicNumbers :: SMALL *
.cpp :(. text + 0xb3): неопределенная ссылка на `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 для этих констант, а enum является синонимом int),Но я действительно хочу спросить: чья это ошибка?
Я виноват в том, что не понял, как работают статические интегральные константы?
Должен ли я винить gcc и надеяться на исправление?(или, возможно, в последней версии уже есть исправление, или, может быть, есть неясный аргумент командной строки, чтобы заставить это работать)?
Между тем, я просто компилирую свой код с оптимизацией, и отладка становится трудной:-O3