I read in the below link that unnamed(anonymous) class should not have static data memebers in it. Could anyone please let me know the reason for it?
https://www-01.ibm.com/support/knowledgecenter/SSLTBW_2.1.0/com.ibm.zos.v2r1.cbclx01/cplr038.htm
says the below..
You can only have one definition of a static member in a program.
Unnamed classes, classes contained within unnamed classes, and local
classes cannot have static data members.
All static member data, if they are ODR-used, must be defined outside the class/struct.
struct Foo
{
static int d;
};
int Foo::d = 0;
If the class/struct is unnamed, there is no way to define the member outside the class.
int ::d = 0;
cannot be used to define the static member of an unnamed class.
Update for C++17
If you are able to use C++17 or newer, you may use
static inline int d = 10;
That will allow a static member variable to be defined in an anonymous class/struct.
Sample code to demonstrate that a static member variable need not be defined outside the class definition:
#include <iostream>
struct foo
{
static inline int d = 10;
};
int main()
{
auto ptr = &foo::d;
std::cout << *ptr << std::endl;
}
Command to build:
g++ -std=c++17 -Wall socc.cc -o socc
Output of running the program:
10
Thanks are due to #Jean-MichaëlCelerier for the suggestion for the update.
Are you sure that the standard actually forbids this?
As mentioned the problem arises as you need to have an actual definition of the static member. The language provides for no method to define it. There is no other problems in referring to it as we can do it from within the struct or via an instance of it.
However GCC for example will accept the following:
static struct {
static int j;
} a;
int main() {
return a.j; // Here we actually refers to the static variable
}
but it can't be linked as a.j refers to an undefined symbol (._0::j), but there's a way to get around this. By defining it in assembler or by using compiler extensions you could. For example adding the line
int j asm("_ZN3._01jE") = 42;
Will make it work. _ZN3._01jE is the real mangled name of the static variable in this case, neither the mangled or unmangled name can be used directly as a identifier in standard C++ (but it can via GCC extension or assembler).
As you must probably realize this would only work with specific compilers. Other compilers would mangle the name in other ways (or even do other things that may make the trick not work at all).
You should really question why you would like to use this trick. If you can do the work using standard methods you should most probably chose that. For example you could reduce the visibility by using anonymous namespace instead for example:
namespace {
static struct Fubar {
static int j;
} a;
Fubar::a = 0;
}
Now Fubar is not really anonymous, but it will at least be confined to the translation unit.
When C++ was standardized, unnamed classes could not have static data members, as there was no way to define/instantiate them. However, this problem has been solved with C++11, as it added the decltype operator:
struct {
static int j;
} a;
// Declare the static member of the unnamed struct:
int decltype(a)::j = 42;
int main() {
return a.j == 42 ? 0 : 1; // Use the static member
}
So, in principle, there could be unnamed classes or structs with static data members. But the C++ standard makers deliberately did not allow this syntax, as the compiler doesn't know, which name it should give to that decltype(a)::j thing for linking. So most (all?) compilers - including current versions of GCC in normal mode - refuse to compile this.
In -fpermissive mode, GCC-9 und GCC-10 accept this code and compile it fine. However, if the declaration of a is moved to a header file, that is included from different source files, they still fail at the linking stage.
So unnamed classes can only be used inside a single translation unit. To avoid polluting the global namespace, just put anything, that needs to stay local, inside an anonymous namespace. So:
namespace {
struct whatever {
static int j;
} a;
int whatever::j = 42;
}
int main() {
return a.j == 42 ? 0 : 1;
}
compiles fine, doesn't pollute global namespace, and even doesn't lead to problems, if the name whatever clashes with a name from another header file.
Related
class Solution {
public:
static int m=INT_MIN; // it shows error: non-const static data member must
be initialized out of line.(why?)
using "int m=INT_MIN" is fine.
int func(TreeNode*root){
if(root==NULL){
return 0;
}
int l=max(func(root->left),0);
int r=max(func(root->right),0);
m=max(l+r+root->val,m);
return max(l,r)+root->val;
}
int maxPathSum(TreeNode* root) {
if(root==NULL)
{
return 0;
}
m=INT_MIN;
int x=func(root);
return m;
}
};
I need to update the value of variable m. Therefore I am using static int data type. But the following error is coming.
Using int instead of static int is working fine. But why is static int giving error?
Bjarne Stroustrup explains this here:
A class is typically declared in a header file and a header file is
typically included into many translation units. However, to avoid
complicated linker rules, C++ requires that every object has a unique
definition. That rule would be broken if C++ allowed in-class
definition of entities that needed to be stored in memory as objects.
As said by Stroustrup, every class needs a unique definition. Now, as we know static members are associated directly with their class. Now consider the two cases:
The static member is also constant, then its initialization is allowed inline because the compiler can make its own optimisations and treat this member as a compile-time constant because it is guaranteed that its value will never change. So, as the value of this member is fixed, the definition of the class with which this member is associated is also fixed. So, the initialization is allowed inline.
The static member is not constant. Then its value can change later on during the execution of the program. So, the compiler can not make compile-time optimisations on this member. Hence, to prevent the complications that may arise while trying to initialize such a member when the class is loaded, inline initialisation of such members is not allowed.
PS: When I heard about this concept the very first time, I was also confused because it is not in accordance with the principle of orthogonality that is a feature desired by programmers. The principle of orthogonality will state that since we can combine int and static; and int and const, we should be able to write static const int and static int in a similar fashion. But this case here is an example of a situation where the developer of a language has to give up orthogonality for the users of the language in exchange of the simplicity of the compilation process.
Have a look at the concept of orthogonality here
To answer OPs question why
class Solution {
public:
int m = INT_MIN;
};
is fine but
class Solution {
public:
static int m = INT_MIN;
};
is not:
In short: Prefixing a data-member with static fundamentally change its meaning.
Without static, the member variable is part of the class and each instance will provide a separate storage for this member variable.
With static, the member variable has only scope of the class but there will be only one global storage.
Respectively, the initialization has different meanings too.
For non-static member variables, it provides a default initialization which constructors may use (or override).
Demonstration by Example:
#include <iostream>
enum ArgCase1 { Case1 };
enum ArgCase2 { Case2 };
class Solution {
public:
int m = 123;
Solution() = default; // will use m(123) implicitly
Solution(ArgCase1) { } // will use m(123) implicitly
Solution(ArgCase2): m(456) { } // default of m ignored
};
#define DEBUG(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
DEBUG(Solution sol);
std::cout << "sol.m: " << sol.m << '\n';
DEBUG(Solution sol1(Case1));
std::cout << "sol1.m: " << sol1.m << '\n';
DEBUG(Solution sol2(Case2));
std::cout << "sol2.m: " << sol2.m << '\n';
}
Output:
Solution sol;
sol.m: 123
Solution sol1(Case1);
sol1.m: 123
Solution sol2(Case2);
sol2.m: 456
Live Demo on coliru
For static member variables, the initialization would be dangerous. Assuming that a class is declared in a header which is included multiple times, this would result in a violation of the One Definition Rule.
In former times, it was usual to declare the static member variable in the header but to define it in the .cpp-file (which represents the translation unit).
Expample:
solution.h:
#ifndef SOLUTION_H
#define SOLUTION_H
class Solution {
public:
static int m;
};
#endif // SOLUTION_H
solution.cc:
// header of this module:
#include "solution.h"
int Solution::m = 123;
Live Demo on coliru
Since C++17, a new alternative is available – using the keyword inline.
From cppreference.com – static members – Static data members
A static data member may be declared inline. An inline static data member can be defined in the class definition and may specify an initializer. It does not need an out-of-class definition
Example:
solution.h:
#ifndef SOLUTION_H
#define SOLUTION_H
class Solution {
public:
inline static int m = 123;
};
#endif // SOLUTION_H
Live Demo on coliru
The advantage is that there is no .cpp-file needed for this i.e. as it is the class Solution could be provided as header-only source.
I define a lot of classes in my cpp files. Often with unimaginative names, such as 'Implementation'. and am worried about name collisions, as these are horrible to debug (assuming the compiler silently drops one of the definitions). However, I also want to be able to debug my program, so anonymous namespaces are not an option. So, can file-scoped (aka. translation-unit scoped) classes be defined in c++ without using namespaces? If yes, how?
File-scoping in c
In c, one can create a global variable with int foo;, and limit the variable to file-scope using static int foo;. Similarly, file-scoped functions are also created with the static keyword, for example static void bar();. And structs do not define data or executable code, and thus are effectively always file-scoped.
Virtual member functions
Now c++ introduced virtual member functions, which caused structs (aka. classes) to contain data and executable code. Hence structs are now globally defined. However, it is not allowed to use static to make the struct file-scoped again. I.e. static struct Foo{}; does not compile.
Namespaces
To tackle the problem of name collisions, c++ also introduced named namespaces. Those can also be used to wrap the struct, such that it becomes pseudo-file-scoped. Though this still forces you to pick a unique name (that you don't even care about) for every file. As a solution, they also introduced anonymous namespaces. Unfortunately, neither gdb nor the visual studio debugger seem to support anonymous namespaces (it is basically impossible to refer to anything inside the anonymous namespace).
A partial solution is to use anonymous structs/classes and typedef these, as both are file-scoped (C - Limit struct Scope), except that it is impossible to explicitly define constructors or destructors (Constructor for a no-named struct). The following example compiles and runs fine with gcc and also allows gdb to put a breakpoint on method():
interface.h:
struct Iface {
virtual void method()=0;
};
implementation_a.cpp and implementation_b.cpp:
#include "interface.h"
typedef struct : Interface {
virtual void method();
} Implementation;
void Implementation::method() {
// Do stuff...
}
Interface * new_implementation_a() { // or new_implementation_b
return new Implementation();
}
main.cpp:
#include "iface.h"
int main() {
Interface * a = new_implementation_a();
Interface * b = new_implementation_b();
a->method();
b->method();
return 0;
}
What is the reasoning to why static const members cannot exist in local classes? It seems like a rather silly restriction.
Example:
void foo() {
struct bar {
int baz() { return 0; } // allowed
static const int qux = 0; // not allowed?!?
};
}
struct non_local_bar {
int baz() { return 0; } // allowed
static const int qux = 0; // allowed
};
Quote from standard (9.8.4):
A local class shall not have static data members.
From the standard section 9.4.2:
If a static data member is of const integral or const enumeration
type, its declaration in the class definition can specify a
constant-initializer which shall be an integral constant expression.
In that case, the member can appear in integral constant expressions
within its scope. 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.
Basically, local classes have no linkage, and static data members require a linkage.
Since there's no way to define a static data member of a local class in namespace scope (a declaration with an initializer is not a definition), they are not allowed, whether they are of const integral type or not. On the surface it may seem like the compiler should just be able to inline the value, but then what happens if you try to access a pointer to the member? With namespace scoped classes you'd just get a linker error, but local classes have no linkage.
I guess in theory they could just allow you to use static const integral types in local classes as long as they are only used in integral constant expressions, but it would probably just put too much of a burden on the standards body and compiler vendors to differentiate for very little practical value; local static variables are accessible from local classes, so using a local static const should be just as good.
I dont think there is a.reason. Normal static datamembers are disallowed because there is no way to define them after being declared.
Also dont forget you can create a local const variable outside the.class that you can use inside the class as long as you only read its value (that is, as long as you dont take.its.address).
Static members of a class need to be defined in global scope, e.g.
abc.h
class myClass {
static int number;
};
abc.cpp
int myClass::number = 314;
Now, since the scope inside void abc(int x) is not global, there is no scope to define the static member.
As things progress, we now have C++11 and with that you can define integral constants variable members in your classes.
class test
{
public:
const int FOO = 123;
[...snip...]
};
That works when you compile with C++11. Notice that the static keyword is not used. When compiling with optimizations turned on, those variables will likely all get optimized out. In debug, though, they appear in your structure as regular variable members.
Note, however, that the size of the class/structure will still include that variable. So here it is likely 4 bytes for the variable FOO.
However, in most cases, classes defined in a function will completely be optimized out so this is a great way of doing things (a good 50% of my classes have such variable members!)
What is the reasoning to why static const members cannot exist in local classes? It seems like a rather silly restriction.
Example:
void foo() {
struct bar {
int baz() { return 0; } // allowed
static const int qux = 0; // not allowed?!?
};
}
struct non_local_bar {
int baz() { return 0; } // allowed
static const int qux = 0; // allowed
};
Quote from standard (9.8.4):
A local class shall not have static data members.
From the standard section 9.4.2:
If a static data member is of const integral or const enumeration
type, its declaration in the class definition can specify a
constant-initializer which shall be an integral constant expression.
In that case, the member can appear in integral constant expressions
within its scope. 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.
Basically, local classes have no linkage, and static data members require a linkage.
Since there's no way to define a static data member of a local class in namespace scope (a declaration with an initializer is not a definition), they are not allowed, whether they are of const integral type or not. On the surface it may seem like the compiler should just be able to inline the value, but then what happens if you try to access a pointer to the member? With namespace scoped classes you'd just get a linker error, but local classes have no linkage.
I guess in theory they could just allow you to use static const integral types in local classes as long as they are only used in integral constant expressions, but it would probably just put too much of a burden on the standards body and compiler vendors to differentiate for very little practical value; local static variables are accessible from local classes, so using a local static const should be just as good.
I dont think there is a.reason. Normal static datamembers are disallowed because there is no way to define them after being declared.
Also dont forget you can create a local const variable outside the.class that you can use inside the class as long as you only read its value (that is, as long as you dont take.its.address).
Static members of a class need to be defined in global scope, e.g.
abc.h
class myClass {
static int number;
};
abc.cpp
int myClass::number = 314;
Now, since the scope inside void abc(int x) is not global, there is no scope to define the static member.
As things progress, we now have C++11 and with that you can define integral constants variable members in your classes.
class test
{
public:
const int FOO = 123;
[...snip...]
};
That works when you compile with C++11. Notice that the static keyword is not used. When compiling with optimizations turned on, those variables will likely all get optimized out. In debug, though, they appear in your structure as regular variable members.
Note, however, that the size of the class/structure will still include that variable. So here it is likely 4 bytes for the variable FOO.
However, in most cases, classes defined in a function will completely be optimized out so this is a great way of doing things (a good 50% of my classes have such variable members!)
const static int foo = 42;
I saw this in some code here on StackOverflow and I couldn't figure out what it does. Then I saw some confused answers on other forums. My best guess is that it's used in C to hide the constant foo from other modules. Is this correct? If so, why would anyone use it in a C++ context where you can just make it private?
A lot of people gave the basic answer but nobody pointed out that in C++ const defaults to static at namespace level (and some gave wrong information). See the C++98 standard section 3.5.3.
First some background:
Translation unit: A source file after the pre-processor (recursively) included all its include files.
Static linkage: A symbol is only available within its translation unit.
External linkage: A symbol is available from other translation units.
At namespace level
This includes the global namespace aka global variables.
static const int sci = 0; // sci is explicitly static
const int ci = 1; // ci is implicitly static
extern const int eci = 2; // eci is explicitly extern
extern int ei = 3; // ei is explicitly extern
int i = 4; // i is implicitly extern
static int si = 5; // si is explicitly static
At function level
static means the value is maintained between function calls.
The semantics of function static variables is similar to global variables in that they reside in the program's data-segment (and not the stack or the heap), see this question for more details about static variables' lifetime.
At class level
static means the value is shared between all instances of the class and const means it doesn't change.
It has uses in both C and C++.
As you guessed, the static part limits its scope to that compilation unit. It also provides for static initialization. const just tells the compiler to not let anybody modify it. This variable is either put in the data or bss segment depending on the architecture, and might be in memory marked read-only.
All that is how C treats these variables (or how C++ treats namespace variables). In C++, a member marked static is shared by all instances of a given class. Whether it's private or not doesn't affect the fact that one variable is shared by multiple instances. Having const on there will warn you if any code would try to modify that.
If it was strictly private, then each instance of the class would get its own version (optimizer notwithstanding).
That line of code can actually appear in several different contexts and alghough it behaves approximately the same, there are small differences.
Namespace Scope
// foo.h
static const int i = 0;
'i' will be visible in every translation unit that includes the header. However, unless you actually use the address of the object (for example. '&i'), I'm pretty sure that the compiler will treat 'i' simply as a type safe 0. Where two more more translation units take the '&i' then the address will be different for each translation unit.
// foo.cc
static const int i = 0;
'i' has internal linkage, and so cannot be referred to from outside of this translation unit. However, again unless you use its address it will most likely be treated as a type-safe 0.
One thing worth pointing out, is that the following declaration:
const int i1 = 0;
is exactly the same as static const int i = 0. A variable in a namespace declared with const and not explicitly declared with extern is implicitly static. If you think about this, it was the intention of the C++ committee to allow const variables to be declared in header files without always needing the static keyword to avoid breaking the ODR.
Class Scope
class A {
public:
static const int i = 0;
};
In the above example, the standard explicitly specifies that 'i' does not need to be defined if its address is not required. In other words if you only use 'i' as a type-safe 0 then the compiler will not define it. One difference between the class and namespace versions is that the address of 'i' (if used in two ore more translation units) will be the same for the class member. Where the address is used, you must have a definition for it:
// a.h
class A {
public:
static const int i = 0;
};
// a.cc
#include "a.h"
const int A::i; // Definition so that we can take the address
It's a small space optimization.
When you say
const int foo = 42;
You're not defining a constant, but creating a read-only variable. The compiler is smart enough to use 42 whenever it sees foo, but it will also allocate space in the initialized data area for it. This is done because, as defined, foo has external linkage. Another compilation unit can say:
extern const int foo;
To get access to its value. That's not a good practice since that compilation unit has no idea what the value of foo is. It just knows it's a const int and has to reload the value from memory whenever it is used.
Now, by declaring that it is static:
static const int foo = 42;
The compiler can do its usual optimization, but it can also say "hey, nobody outside this compilation unit can see foo and I know it's always 42 so there is no need to allocate any space for it."
I should also note that in C++, the preferred way to prevent names from escaping the current compilation unit is to use an anonymous namespace:
namespace {
const int foo = 42; // same as static definition above
}
It's missing an 'int'. It should be:
const static int foo = 42;
In C and C++, it declares an integer constant with local file scope of value 42.
Why 42? If you don't already know (and it's hard to believe you don't), it's a refernce to the Answer to Life, the Universe, and Everything.
C++17 inline variables
If you Googled "C++ const static", then this is very likely what you really want to use are C++17 inline variables.
This awesome C++17 feature allow us to:
conveniently use just a single memory address for each constant
store it as a constexpr: How to declare constexpr extern?
do it in a single line from one header
main.cpp
#include <cassert>
#include "notmain.hpp"
int main() {
// Both files see the same memory address.
assert(¬main_i == notmain_func());
assert(notmain_i == 42);
}
notmain.hpp
#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP
inline constexpr int notmain_i = 42;
const int* notmain_func();
#endif
notmain.cpp
#include "notmain.hpp"
const int* notmain_func() {
return ¬main_i;
}
Compile and run:
g++ -c -o notmain.o -std=c++17 -Wall -Wextra -pedantic notmain.cpp
g++ -c -o main.o -std=c++17 -Wall -Wextra -pedantic main.cpp
g++ -o main -std=c++17 -Wall -Wextra -pedantic main.o notmain.o
./main
GitHub upstream.
See also: How do inline variables work?
C++ standard on inline variables
The C++ standard guarantees that the addresses will be the same. C++17 N4659 standard draft
10.1.6 "The inline specifier":
6 An inline function or variable with external linkage shall have the same address in all translation units.
cppreference https://en.cppreference.com/w/cpp/language/inline explains that if static is not given, then it has external linkage.
GCC inline variable implementation
We can observe how it is implemented with:
nm main.o notmain.o
which contains:
main.o:
U _GLOBAL_OFFSET_TABLE_
U _Z12notmain_funcv
0000000000000028 r _ZZ4mainE19__PRETTY_FUNCTION__
U __assert_fail
0000000000000000 T main
0000000000000000 u notmain_i
notmain.o:
0000000000000000 T _Z12notmain_funcv
0000000000000000 u notmain_i
and man nm says about u:
"u" The symbol is a unique global symbol. This is a GNU extension to the standard set of ELF symbol bindings. For such a symbol the dynamic linker will make sure that in the entire process
there is just one symbol with this name and type in use.
so we see that there is a dedicated ELF extension for this.
Pre-C++ 17: extern const
Before C++ 17, and in C, we can achieve a very similar effect with an extern const, which will lead to a single memory location being used.
The downsides over inline are:
it is not possible to make the variable constexpr with this technique, only inline allows that: How to declare constexpr extern?
it is less elegant as you have to declare and define the variable separately in the header and cpp file
main.cpp
#include <cassert>
#include "notmain.hpp"
int main() {
// Both files see the same memory address.
assert(¬main_i == notmain_func());
assert(notmain_i == 42);
}
notmain.cpp
#include "notmain.hpp"
const int notmain_i = 42;
const int* notmain_func() {
return ¬main_i;
}
notmain.hpp
#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP
extern const int notmain_i;
const int* notmain_func();
#endif
GitHub upstream.
Pre-C++17 header only alternatives
These are not as good as the extern solution, but they work and only take up a single memory location:
A constexpr function, because constexpr implies inline and inline allows (forces) the definition to appear on every translation unit:
constexpr int shared_inline_constexpr() { return 42; }
and I bet that any decent compiler will inline the call.
You can also use a const or constexpr static variable as in:
#include <iostream>
struct MyClass {
static constexpr int i = 42;
};
int main() {
std::cout << MyClass::i << std::endl;
// undefined reference to `MyClass::i'
//std::cout << &MyClass::i << std::endl;
}
but you can't do things like taking its address, or else it becomes odr-used, see also: Defining constexpr static data members
C
In C the situation is the same as C++ pre C++ 17, I've uploaded an example at: What does "static" mean in C?
The only difference is that in C++, const implies static for globals, but it does not in C: C++ semantics of `static const` vs `const`
Any way to fully inline it?
TODO: is there any way to fully inline the variable, without using any memory at all?
Much like what the preprocessor does.
This would require somehow:
forbidding or detecting if the address of the variable is taken
add that information to the ELF object files, and let LTO optimize it up
Related:
C++11 enum with class members and constexpr link-time optimization
Tested in Ubuntu 18.10, GCC 8.2.0.
According to C99/GNU99 specification:
static
is storage-class specifier
objects of file level scope by default has external linkage
objects of file level scope with static specifier has internal linkage
const
is type-qualifier (is a part of type)
keyword applied to immediate left instance - i.e.
MyObj const * myVar; - unqualified pointer to const qualified object type
MyObj * const myVar; - const qualified pointer to unqualified object type
Leftmost usage - applied to the object type, not variable
const MyObj * myVar; - unqualified pointer to const qualified object type
THUS:
static NSString * const myVar; - constant pointer to immutable string with internal linkage.
Absence of the static keyword will make variable name global and might lead to name conflicts within the application.
In C++,
static const int foo = 42;
is the preferred way to define & use constants. I.e. use this rather than
#define foo 42
because it doesn't subvert the type-safety system.
To all the great answers, I want to add a small detail:
If You write plugins (e.g. DLLs or .so libraries to be loaded by a CAD system), then static is a life saver that avoids name collisions like this one:
The CAD system loads a plugin A, which has a "const int foo = 42;" in it.
The system loads a plugin B, which has "const int foo = 23;" in it.
As a result, plugin B will use the value 42 for foo, because the plugin loader will realize, that there is already a "foo" with external linkage.
Even worse: Step 3 may behave differently depending on compiler optimization, plugin load mechanism, etc.
I had this issue once with two helper functions (same name, different behaviour) in two plugins. Declaring them static solved the problem.
Yes, it hides a variable in a module from other modules. In C++, I use it when I don't want/need to change a .h file that will trigger an unnecessary rebuild of other files. Also, I put the static first:
static const int foo = 42;
Also, depending on its use, the compiler won't even allocate storage for it and simply "inline" the value where it's used. Without the static, the compiler can't assume it's not being used elsewhere and can't inline.
This ia s global constant visible/accessible only in the compilation module (.cpp file). BTW using static for this purpose is deprecated. Better use an anonymous namespace and an enum:
namespace
{
enum
{
foo = 42
};
}
Making it private would still mean it appears in the header. I tend to use "the weakest" way that works. See this classic article by Scott Meyers: http://www.ddj.com/cpp/184401197 (it's about functions, but can be applied here as well).