static double m = 30000;
double foo(double x, double y) {
return x/m + y;
}
Это ничего не выиграет. Для выполнения вычисления должна быть сделана копия m.
Также если вы делаете:
double bar( double x, double y) {
m += x + y;
return m;
}
Тогда все звонки на бар изменится m.
Статические переменные вне функций (или классов) - это действительно глобальные переменные с областью действия файла. Другие файлы не могут получить их по extern
Статические переменные внутри функции по-прежнему похожи на глобальные переменные, за исключением того, что даже другие функции в том же файле не могут видеть их напрямую.
const double m = 30000;
Это лучше, а во многих случаях лучше. Если компилятор видит этот глобальный констант, а затем видит ссылку на m, он знает, что вместо того, чтобы генерировать код для загрузки значения, где бы он ни находился (что, вероятно, сначала требует загрузки буквального адреса в регистр) в регистр или позицию стека чтобы делать вычисления, он может просто сделать регистр 30000 или иногда сгенерировать инструкцию с 30000, закодированными прямо там.
Обратной стороной этого является то, что компилятор должен предположить, что другие souce-файлы захотят прочитать m и должен фактически сохранить копию как переменную (но постоянную переменную) в объектном файле.
Я не уверен, является ли он стандартным, но иногда вы можете сделать extern const double m = 30000;
, и компилятор будет использовать 30000 для оптимизации и предположить, что в другом файле есть копия m, которая будет сохранена в исполняемом файле. Вы также можете сделать static const double m = 30000;
, и компилятор может предположить, что никто не будет ожидать, что копия m хранится в объектном коде, сгенерированном из этого исходного файла.
Doing
#define m 30000
более рискованно. Вы не получите предупреждение или ошибку, если ранее был другой m, объявленный как переменная, константа или функция. Кроме того, для таких макросов препроцессора это легко испортить.
Например:
#define BASE_ADDRESS 48
#define MY_OFFSET 9
#define MY_ADDRESS BASE_ADDRESS+MY_OFFSET
...
return MY_ADDRESS*4;
Да, это глупый пример, но как это выглядит после того, как препроцессор покончил с этим, это
...
return 48+9*4;
Что такое
return 48+(9*4);
И это не то, что вы, вероятно, хотели.
Другое место, где макросы плохие, это когда у вас есть большие константы, такие как строки. Строки требуют, чтобы они были адресуемыми по указателю и их было сложнее оптимизировать, чем целые числа и литеральные или постоянные числа с плавающей запятой. Вы могли бы легко сделать очень большую программу, если бы у вас было много таких вещей, как:
#define JIM "Jim"
#define JOHN "John"
, а затем использовал JIM и JOHN во всех ваших программах, потому что компилятор может не увидеть, что вам действительно нужны только строки "Jom" и "John" в программе.
При этом нередки случаи, когда константы объявляются таким образом, и часто они правильно делают это люди, которые знают, что они делают.