What is the difference between these three statements?
static const int foo = 42;
const int foo = 42;
#define foo 42
2) const int foo = 42;
This is an int variable whose value you can't change.
1) static const int foo = 42;
This is the same as 2), but it's only visible in the source code file that it's in. So you can't use it in another .cpp file for example if you compile them separately and then link together. By using static with variables and functions you allow the compiler to optimize them better because the compiler can rely on that it knows all situations where that variable or function is used. The word static has different meanings in different situations, but this is its behavior if you use it in the global level. If you use this inside a function, it has a different meaning. Then it means that this variable is only initialized once and it stays in the memory no matter how many times the code execution passes that definition. This has more meaning if you don't use const at the same time, because then you can change the value of the variable and it will "remember" that value even when you exit the part of code where that variable is visible (called "scope") and re-enter it.
3) #define foo 42
This is a precompiler macro. So the precompiler will substitute all "foo"s with the number 42 before giving to code to the actual compiler. Some years ago people used this approach because it was faster than const variables, but nowadays they are equally fast.
static const int foo = 42;
What this does depends on where it is found and what language you are using:
If this is a declaration at namespace scope (in C++) or file scope (in C), then it declares and defines a const-qualified object named foo that has internal linkage (this means that the name foo only refers to this object in the current translation unit, not in other translation units).
If this is a declaration at function scope (in C or C++), then it declares and defines a const-qualified object named foo that has no linkage (locally declared variables don't have linkage) and the lifetime of that object is the duration of the program (this means that in every call to the function, foo refers to the same object).
If this is C++ and this is a declaration inside of a class, then it declares but does not define a const-qualified static data member named foo that has external linkage (this means that the name foo (in this case, when qualified with the class name) refers to the same object when used in any translation unit).
const int foo = 42;
What this does depends on what language you are using and where the declaration appears. If the declaration is at namespace or file scope, then
In C++ this declares and defines a const-qualified object named foo that has internal linkage (the const implies internal linkage in C++).
In C this declares and defines a const-qualified object named foo that has external linkage (the const does not imply internal linkage in C).
In both C++ and C, if this declaration is at function scope, then this declares and defines a const-qualified local variable named foo that has no linkage.
#define foo 42
This does not define an object; it defines a macro named foo that is replaced by the token sequence consisting of a single token, 42.
The const modifier is used to specify that foo is a constant. i.e. After initialisation, its value may not be changed.
The static keyword is used to to tell the compiler that the value of the variable you're declaring as static should be retained even when it goes out of scope. This means that if you declare a variable static inside a function, it's value will be remembered even after the function returns (unlike automatic variables). It's also used to tell the compiler that a variable is visible only within the current unit of compilation. This means if that you declare a top level variable/function static, it's not visible from other files that you're compiling along with this one.
#define is a preprocessor directive that performs textual substitution on all occurrences of (in this case) foo before actual compilation takes place. The compiler doesn't even see foo. It only sees 42.
First two declare a variable called foo, while the third one doesn't declare any variable, it's just an alias of 42.
In C, first one is a file-cope variable, while the second one has external linkage, means it can be referred to from another translation unit!
But in C++, both ( first and second) are same, because in C++ const are static by default; both has internal linkage!
static const int foo = 42;
A constant static variable. The value once initialized can't be changed as long as the variable exists. Being static the variable can't be included in any files even if the file in which it is declared is included. If this is member of a class then only one copy of the variable exists for all the instances of the class.
const int foo = 42;
A constant variable where the value once initialized stays and cant be changed.
#define foo 42
Not a variable but a symbolic constant. so operations like &foo are not allowed. foo only serves as an alias to 42. Unlike others this is processed by the preprocessor .
What does static mean? hint: fgbentr fcrpvsvre
What does const mean? hint: ernq-bayl inevnoyr
What does #define do? In what stage of compilation does it take place? What's that mean for generated code?
Related
Hello if I have a static const data member then I can provide an in-class initializer for it and I don't need to define it again outside of the class body.
But that is true only if that constant is used within the class scope and if used outside, a separate definition outside must be supplied otherwise any reference to it causes a link-time error: "undefined reference to static object: x".
struct Foo{
static int const sz_ = 100;
std::array<int, sz_> ai_100{};
};
//int const Foo::sz_;
int main(){
float pts[Foo::sz_]{}; // ok
void bar(int const&); // defined later on
bar(Foo::sz_); // undefined reference to Foo::sz_
}
void bar(int const&){
//do_something
}
Why when used the static const data member sz_outside of the class scope as the array size is OK?
Why when passing sz to function bar which takes an l-value reference to const the linker fails to link and complain about the definition of Foo::sz_?
The function bar takes an l-value reference to const int& so it can be initialized from an r-value so why it matters about the definition of the initializer Foo::sz_?
Why we need a separate definition for a static const data member?
First, we must remember the One Definition Rule. It's actually a set of rules, but a simplified version of the rule that we are interested in this context is: There must be exactly one definition of every variable.
Secondly, we should consider that classes are often used in more than one translation unit.
If the declaration of the static member variable was a definition, then every translation unit that includes contains the class definition would contain that variable definition. That would be contrary to the ODR, and the linker wouldn't know what to do.
As such, there must be a separate definition of the variable which allows the class definition to be included into multiple translation unit while keeping the separate variable definition in one translation unit.
While the language implementations of past may not have been able to deal with multiple definitions (back before templates were in C++), these days they are, and the language has been expanded (in C++17) to allow inline definitions of variables. inline keyword has the same meaning for variable as it has for functions: It relaxes the One Definition Rule allowing (and also requiring) the variable to be defined in every TU (where it is odr-used).
Mostly for historical reasons. Staring with C++17, you can have inline data members. And constexpr members are inline by default.
Your non-linking example can be simplified to:
struct Foo{
static int const sz_ = 100;
};
int main(){
int const *p = &Foo::sz_; // undefined reference to Foo::sz_
}
In other words, if we take the address of Foo::sz_, or assign a reference to it (which is a very similar operation, under the hood), then we need to define int const Foo::sz_; somewhere.
Why is this? Well, if we just use the value of Foo::sz_, then the compiler doesn't need a variable. It can just use 100 as, effectively, a literal. But if we want to take the address of it then we need an actual variable to refer to.
In the C++11 standard, what is the difference between constexpr and static constexpr global variables when defined in a header? More specifically, when multiple translation units include the same header, which declaration (if any) is guaranteed to define the same variable across the translation units?
e.g.,
cexpr.h:
#ifndef CEXPR_H
#define CEXPR_H
constexpr int cint = 1;
static constexpr int scint = 1;
#endif
a.cpp:
#include "cexpr.h"
b.cpp:
#include "cexpr.h"
In your current example there is no difference: On variable declarations, constexpr implies const, and a const variable at namespace scope has internal linkage by default (so adding static does not change anything).
In C++14, you cannot declare a variable as constexpr and have it have external linkage unless you only ever do this in one single translation unit. The reason is that constexpr variables require an initializer, and a declaration with initializer is a definition, and you must only have a single definition.
However, what you can do is use a normal integral constant, which you can declare (not define) as extern, and in the translation unit where it is defined it can even be used as a constant expression:
lib.h:
extern const int a;
lib.cpp:
#include "lib.h"
const int a = 10;
int b[a] = {1, 2, 3}; // OK in this translation unit
In C++17, there is a new feature "inline variables" which lets you say:
inline constexpr int a = 10;
And this is an "inline definition" that can appear repeatedly, and each definition defines the same entity (just like all the other "inline" entities in the language).
I think this article explains more clear. 6.8 — Global constants and inline variables
Because const globals have internal linkage, each .cpp file gets an independent version of the global variable that the linker can’t see. In most cases, because these are const, the compiler will simply optimize the variables away.
The term “optimizing away” refers to any process where the compiler optimizes the performance of your program by removing things in a way that doesn’t affect the output of your program. For example, lets say you have some const variable x that’s initialized to value 4. Wherever your code references variable x, the compiler can just replace x with 4 (since x is const, we know it won’t ever change to a different value) and avoid having to create and initialize a variable altogether.
So, the "cint " and "scint" are all internal linkage variables.
The best practice to define global variable after C++ 17:
inline constexpr double pi = 0;
Working Mechanism:
C++17 introduced a new concept called inline variables. In C++, the term inline has evolved to mean “multiple definitions are allowed”. Thus, an inline variable is one that is allowed to be defined in multiple files without violating the one definition rule. Inline global variables have external linkage by default.
Inline variables have two primary restrictions that must be obeyed:
1) All definitions of the inline variable must be identical (otherwise, undefined behavior will result).
2) The inline variable definition (not a forward declaration) must be present in any file that uses the variable.
The compiler will consolidate all inline definitions into a single variable definition. This allows us to define variables in a header file and have them treated as if there was only one definition in a .cpp file somewhere. These variables also retain their constexpr-ness in all files in which they are included.
If you can, prefer the static constexpr because with the constexpr it depends on the toolchain how likely it will get done on compile-time. Gcc is most aggressive, MSVS least aggressive and clang is in between.
Instead of leaving some values up to optimizer to decide it will do it at compile-time be more explicit and force it.
Reference:
https://www.youtube.com/watch?v=4pKtPWcl1Go
This question already has answers here:
What is the difference between a definition and a declaration?
(27 answers)
Closed 7 years ago.
My question stems from studying Effective C++ by Scott Meyers.
In Item II of that book, following is written :
To limit the scope of a constant to a class, you must make it a member and, to ensure there's at most one copy of the constant, you must make it a static member.
That is correctly written. Then immediately the following example is given :
class GamePlayer {
private:
static const int NumTurns = 5;
int scores[NumTurns];
....
};
Then the following is written pertaining to the above example :
What you see above is a declaration and not a definition of NumTurns.
My First question is : What is the meaning of this statement ?
Immediately after that the following is mentioned :
Usually C++ requires that you provide a definition for anything you use, but class specific constants that are static and of integral type (e.g - integers, chars, bools) are an exception. As long as you don't take their address, you can declare them and use them without providing a definition. If you do take the address of a class constant, or if your compiler incorrectly insists on a definition even if you don't take the address, you provide a separate definition like this :
const int GamePlayer::Numturns; //definition of NumTurns
Why now it is a definition and not a declaration ?
I understand the difference in the context of a function but do not understand it in the context of a regular variable. Also, can someone expand on what the author means by
... if you do take the address of a class constant, or if your ..
part of the above quoted paragraph ?
P.S : I am a relatively newbie in C++.
Just as with functions, variables can have 'purely declarative' declarations, and actual definitions. You're confused because you probably didn't encounter many pure variable declarations before.
int i; // Definition
extern int i, j; // (Re)declares i, and declares j
extern int j = 0; // Defines j (confusing, eh?)
As you're used to with functions, definitions are declarations, but not all declarations are definitions. §3.1/2 reads
A declaration is a definition unless […] it declares a static data
member in a class definition (9.2, 9.4),
Thus in-class static data member declarations are never defining the variables they declare. However, sometimes, a variables definition doesn't have to be present. That is the case when you can use its value directly without necessitating the variables run-time existence.
In technical terms, as long as a static data member (or any entity, for that matter) is not 'odr-used', it doesn't have to be defined. Odr-use for all entities is defined in §3.2/3:
A variable x whose name appears as a potentially-evaluated expression
ex is odr-used by ex unless applying the lvalue-to-rvalue conversion
(4.1) to x yields a constant expression (5.20) that does not invoke
any non-trivial functions and, if x is an object, ex is an element of
the set of potential results of an expression e, where either the
lvalue-to-rvalue conversion (4.1) is applied to e, or e is a
discarded-value expression (Clause 5).
This looks complicated, and it was simpler in earlier versions of the standard. However, it roughly says that the variable is not odr-used by some expression when that expression "immediately" accesses the variables value, and this access yields a constant expression. Meyers example of "taking its address" is only one of many for odr-use.
For some class A and its static data member i,
class A {
static const int i = 57; // Declaration, not definition
};
const int A::i; // Definition in namespace scope. Not required per se.
It is stated here that:
Static const integral data members initialized in the class interface are not addressable variables. They are mere symbolic names for their associated values. Since they are not variables, it is not possible to determine their addresses. Note that this is not a compilation problem, but a linking problem. The static const variable that is initialized in the class interface does not exist as an addressable entity.
What "addressable entity" refers here is "instance" of static const data type. No instance, no address, i.e its only a declaration.
Note that static variables that are explicitly defined in a source file can be linked correctly, though.
class X
{
public:
static int const s_x = 34;
static int const s_y;
};
int const X::s_y = 12;
int main()
{
int const *ip = &X::s_x; // compiles, but fails to link
ip = &X::s_y; // compiles and links correctly
}
... if you do take the address of a class constant, or if your .. part of the above quoted paragraph ?
It means if such a member is odr-used, a definition at namespace scope is still required, but it should not have an initializer.
struct X {
const static int n = 1;
};
const int* p = &X::n; // X::n is odr-used
const int X::n; // ... so a definition is necessary
Why now it is a definition and not a declaration ?
Because this statement causes the compiler to generate an address for the static variable.
Also, can someone expand on what the author means by "if you do take
the address of a class constant":
When you make a pointer point to a variable you take its address.
A short answer is: a declaration says "this thing exists somewhere", and a definition causes the space to be allocated. In your case, you've declared it to be static and const. The compiler may be smart enough to notice that if you only ever use it as a value, it can simply replace that usage with the literal 5. It doesn't need to actually make space for a variable somewhere and fill it with the 5, it can use the 5 directly at compile-time. However, if you take the address of it, the compiler can no longer make that assumption and now needs to put that 5 into somewhere addressable. The compiler needs it to exist in one translation unit (roughly: one cpp file. See also the One Definition Rule.), so now you have to explicitly declare it somewhere.
I am new to C++.
I have a class like this:
class CodeTest
{
private:
static const int TOTAL=100;
};
Is TOTAL a declaration or a definition?
When I was reading Scott Meyer's book, it was mentioned that in the implementation file we need to define something like:
const int CodeTest::TOTAL;
Why is this required?
The declaration in an implementation file outside of the header is required because otherwise every translation unit that includes this header would define its own object (that is, its own storage for the variable).
This would violate the One Definition Rule. A consequence would be e.g. that if the variable was changed in one translation unit, this change would be invisible to other translation units. Now, this isn’t that relevant since the variable is constant. However, taking its address would also yield different pointers in different translation units.
Since this stirred up some controversy, I looked in the standard, and #Nawaz is right, I was wrong.
9.4.2/2
If a static data member is of const integral type [...]. The member
shall still be defined in a namespace scope if it is used in the
program and the namespace scope definition shall not contain an
initializer.
So what you have there is a declaration, and the variable is initialized to a value. Outside the class you must define the variable, but not assign a value to it.
The part with const integral type only applies to this particular case - i.e. you can initialize said type inside the class, but all static data members must be defined outside.
To answer the question:
Regardless of whether the definition is or isn't required outside the class (depending on whether you use the member or not), whatever is inside the class (initialized or not) is just a declaration.
First part of the question:
This line: static const int TOTAL=100; is a declaration followed by an initialisation.
TOTAL is an identifier.
Second part of the question
const int CodeTest::TOTAL is required to initialize the variable.
static const int TOTAL=100; // is a declaration followed by an initialisation.
From the C++ standard section 3.1:
A declaration introduces names into a translation unit or redeclares names introduced by previous declarations. A declaration specifies the interpretation and attributes of these names.
The next paragraph states that a declaration is a definition unless...... it declares a static member within a class definition:
struct X
{
int a; // defines a
static int b; // declares b
};
You can read more about definition and declaration here: SO: What is the difference between a definition and a declaration?
When you have a static global variable in a C++ header file, each translation unit that includes the header file ends up with its own copy of the variable.
However, if I declare a class in that same header file, and create a member function of that class, implemented inline within the class declaration, that uses the static global variable, for example:
#include <iostream>
static int n = 10;
class Foo {
public:
void print() { std::cout << n << std::endl; }
};
then I see slightly odd behavior under gcc 4.4:
If I compile without optimization, all uses of the member function use the copy of the variable from one of the translation units (the first one mentioned on the g++ command line).
If I compile with -O2, each use of the member function uses the copy of the variable from the translation unit in which the case is made.
Obviously this is really bad design, so this question is just out of curiosity. But my question, nonetheless, is what does the C++ standard say about this case? Is g++ behaving correctly by giving different behavior with and without optimization enabled?
The standard says (3.2/5):
There can be more than one definition
of a class type (clause 9),
... provided the definitions satisfy
the following requirements ... in each
definition of D, corresponding names,
looked up according to 3.4, shall
refer to an entity defined within the
definition of D, or shall refer to the
same entity
This is where your code loses. The uses of n in the different definitions of Foo do not refer to the same object. Game over, undefined behavior, so yes gcc is entitled to do different things at different optimization levels.
3.2/5 continues:
except that a name can refer to a
const object with internal or no
linkage if the object has the same
integral or enumeration type in all
definitions of D, and the object is
initialized with a constant expression
(5.19), and the value (but not the
address) of the object is used, and
the object has the same value in all
definitions of D
So in your example code you could make n into a static const int and all would be lovely. It's not a coincidence that this clause describes conditions under which it makes no difference whether the different TUs "refer to" the same object or different objects - all they use is a compile-time constant value, and they all use the same one.