Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should I use static data members vs. const global variables?

Declaring const global variables has proven useful to determine some functioning parameters of an API. For example, on my API, the minimum order of numerical accuracy operators have is 2; thus, I declare:

const int kDefaultOrderAccuracy{2};

as a global variable. Would it be better to make this a static const public data member of the classes describing these operators? When, in general, is better to choose one over the other?

like image 334
Eduardo Avatar asked Nov 27 '22 14:11

Eduardo


1 Answers

const int kDefaultOrderAccuracy{2};

is the declaration of a static variable: kDefaultOrderAccuracy has internal linkage. Putting names with internal linkage in a header is obviously an extremely bad idea, making it extremely easy to violate the One Definition Rule (ODR) in other code with external linkage in the same or other header, notably when the name is used in the body of an inline or template function:

Inside f.hpp:

template <typename T>
const T& max(const T &x, const T &y) {
  return x>y ? x : y;
}

inline int f(int x) {
  return max(kDefaultOrderAccuracy, x); // which kDefaultOrderAccuracy?
}

As soon as you include f.hpp in two TU (Translation Units), you violate the ODR, as the definition is not unique, as it uses a namespace static variable: which kDefaultOrderAccuracy object the definition designates depends on the TU in which it is compiled.

A static member of a class has external linkage:

struct constants {
  static const int kDefaultOrderAccuracy{2};
};

inline int f(int x) {
  return max(constants::kDefaultOrderAccuracy, x); // OK
}

There is only one constants::kDefaultOrderAccuracy in the program.

You can also use namespace level global constant objects:

extern const int kDefaultOrderAccuracy;
like image 69
curiousguy Avatar answered Dec 06 '22 04:12

curiousguy