![]() With extern, the above code is a declaration, and not a definition. It looks somewhat similar to inline, but its effect is very different. How to share a global constant across multiple files before C++17? Before C++17: the extern keywordīefore C++17, one way to fix the problem is to use the extern keyword in the header file: extern X const x Static inline std::string const S = "Forty-Two" īut not everyone compiles their code in C++17, at least at the time of this writing. With inline, we can define it and declare it at the same time: // header file With this change our program now correctly outputs: X constructed inline and class constantsĬonstants inside of a class, declared static, have the same scope as global constants, and inline simplified their definition in C++17 too.īefore C++17, we had to follow the annoying pattern of declaring the static in the class definition, and define it outside in only one cpp file: // header file Note that this usage of inline has (to my knowledge, correct me if I’m wrong in the comments section) nothing to do with copying code at call site, like with inline functions. This tells the compiler to not to define the object in every file, but rather to collaborate with the linker in order to place it in only one of the generated binary files. The solution in C++17 is to add the inline keyword in the definition of x: inline X const x This feature of C++ makes the language a little harder to learn). (I write “simple” between quotes because even if it is simpler than the solution before C++17, the real simplest way should be the natural above way. How to fix it then? In C++17: inline variablesĬ++17 offers a “simple” solution to this. With this addition, here is what our program with the two. Let’s make a simple test to observe it with our own eyes: let’s add a side effect in the constructor of X: class X Given that writing X const x is such a natural thing to do (another hat tip to the const Westerners), you may doubt that such problems could appear. But if the two objects are created, then they would consume more memory and two constructors (and destructors) would be called. Strictly speaking, the undefined behaviour makes the last two reasons rather theoretical, because in undefined behaviour anything can happen. if the constructor (or destructor) of X has side effects, they will be executed twice.But their order of initialisation is undefined, so it’s unspecified behaviour, for global constants, since they have internal linkage we’re having several independent objects created.for global variables, it is undefined behaviour (objects must be defined only once in C++),.cpp file contains: X const x Įach file has its own version of x. So after the preprocessor expansion, each of the two. How so? The preprocessor #include directives essentially copy-paste the code of header.h into each. This code compiles, but doesn’t define a global constant! cpp file.īut what if X is defined this way in a header file, which is #included in several. ![]() This works ok (assuming that X has a default constructor) when X is defined and used only inside a. E verything here holds with const X x (friendly hat tip to the folks on the West side of the const ). ![]() Even though I’m an East const person, none of the contents of this post has anything to do with putting const before or after the type. ![]() Note: Maybe it would seem more natural for you to read const X x. To define a constant of type X, the most natural way is this: X const x Thanks a lot to Patrice Roy for reviewing this article and helping me with his feedback! Declaring a global constant: the natural but incorrect way Constant values are an everyday tool to make code more expressive, by putting names over values.įor example, instead of writing 10 you can write MaxNbDisplayedLines to clarify your intentions in code, with MaxNbDisplayedLines being a constant defined as being equal to 10.Įven though defining constants is such a basic tool to write clear code, their definition in C++ can be tricky and lead to surprising (and even, unspecified) behaviour, in particular when making a constant accessible to several files.Įverything in this article also applies to global variables as well as global constants, but global variables are a bad practice contrary to global constants, and we should avoid using them in the first place. ![]()
0 Comments
Leave a Reply. |