Этот вопрос тесно связан с впоследствии заданным вопросом Вот.
Описан метод определения констант в классе. Вот по Страуструпу.
Когда я следую методу Страуструпа, я вижу ожидаемые результаты. Однако в Visual Studio 2010 отладчик не может разрешить static const
член класса в рамках этого класса.
Вот что я имею в виду:
#include <iostream>
class Foo {
public:
static const int A = 50;
char arr[A];
void showA();
};
void Foo::showA() {
std::cout << "showA = " << A << "\n";
}
int main() {
Foo f;
f.showA();
}
Когда отладчик находится в showA (), окно «watch» сообщает:
Error: Symbol "Foo::A" not found
Я хотел бы подчеркнуть, что программа ведет себя так, как и ожидалось, то есть вывод:
showA = 50
и программа возвращает 0.
Кто-нибудь еще может воспроизвести это с Visual Studio 2010? Это ошибка в отладчике?
Visual C ++ ошибочно предоставляет слабое определение (доказательства, представленные в этом ответе) основываясь на объявлении внутри класса, несмотря на ясную формулировку в Стандарте:
Объявление статического члена данных в его определении класса не является определением и может быть неполного типа, кроме cv-квалифицированного
void
, Определение для статического члена данных должно появиться в области пространства имен, включающей определение класса члена. В определении в области пространства имен имя члена статических данных должно быть квалифицировано по имени его класса с использованием::
оператор.
Согласно другому правилу в Стандарте, определение не требуется, если член не УСО используемый.
Независимо от того, существует ли в Visual C ++ явное или слабое определение, ошибочно предоставленное, разница не имеет. Если участник не УСО используемый, компоновщик не увидит никаких ссылок на него и удалит его, в результате чего отладчик не сможет понять, существовал ли он когда-либо. С помощью компоновщика Microsoft вы можете запретить эту оптимизацию, используя /OPT:NOREF
,
В конечном счете, это не то, что вы хотите делать в рабочем коде, поскольку в вашей прикладной программе останутся все виды рудиментарных вещей из стандартной библиотеки. Но для временного использования во время отладки это разумная настройка.
Вы можете добавить определение для вашего статического члена данных в глобальной области пространства имен:
const int Foo::A;
Добавление определения члена статических данных, которое не обязательно, но разрешено, похоже, решит вашу проблему.
Я проверил это на отладочной сборке с VS2010, и значение A
правильно отображается в окне отладки, когда определение присутствует (в то время как сообщение об ошибке сообщается, когда определение отсутствует, в соответствии с тем, что вы упоминаете).
Это не ошибка. Компилятор может (и почти всегда) оптимизирует статические константы базовых типов. Вместо выделения памяти для A
компилятор просто указывает на значение A
в скомпилированные инструкции.
Так как A
нигде не хранится, у него нет адреса, поэтому отладчик не может его просмотреть.