Is there a use for flagging a variable as static, when it lies in the global scope of a .cpp file, not in a function?
Can you use the static keyword for functions as well? If yes, what is their use?
Yes, if you want to declare file-scope variable, then static keyword is necessary. static variables declared in one translation unit cannot be referred to from another translation unit.
By the way, use of static keyword is deprecated in C++03.
The section $7.3.1.1/2 from the C++ Standard (2003) reads,
The use of the static keyword is
deprecated when declaring objects in a
namespace scope; the
unnamed-namespace provides a superior
alternative.
C++ prefers unnamed namespace over static keyword. See this topic:
Superiority of unnamed namespace over static?
In this case, keyword static means the function or variable can only be used by code in the same cpp file. The associated symbol will not be exported and won't be usable by other modules.
This is good practice to avoid name clashing in big software when you know your global functions or variables are not needed in other modules.
Taking as an example -
// At global scope
int globalVar; // Equivalent to static int globalVar;
// They share the same scope
// Static variables are guaranteed to be initialized to zero even though
// you don't explicitly initialize them.
// At function/local scope
void foo()
{
static int staticVar ; // staticVar retains it's value during various function
// function calls to foo();
}
They both cease to exist only when the program terminates/exits.
Related
I am working with a class whose constructor declares and initializes a static const variable in the implementation. This is not a data member of the class. I understand the use of const in this context, but what is gained by using static?
I understand that the static const global constants are shared by all instances of the class. Does that also happen with the variable inside the constructor?
Also, why would this not be defined at the Global scope, like the other two? That's where I would normally define my constants.
Example Code:
#includes...
static const int GLOBAL_CONST1 = 100;
static const double GLOBAL_CONST2 = 1.0;
SomeClass::SomeClass()
:
theDataMember1 (),
theDataMember2 (),
...
{
static const double SOME_VAR = 0.01; // Why not declare this globally?
theDataMember1 = SomeIncludedClass(SOME_VAR);
}
Static Variable gets constructed only once no matter how many times the function is called.
So in case your defining constants inside a function and the function is called multiple times, then to reduce the cost of constructing this object every time the function is called you would make it a static variable (Mainly useful when its a constant, Else you may end up changing this value and it soon gets messed up).
For your second question, This is because you don't want others to be able to access the value of variable "SOME_VAR". Giving a global scope means any one can access it.
This link provides a good example about how local static is sometimes useful than global static variables.
When the constant is used only in one single function it can make sense to declare it only in the scope of the function it is used in. Why the static is used here does not really make sense to me, because it will be the same in all instances of the class anyway since it is a compile time constant.
But:
You can also initialize the constant from parameters computed at runtime. In that case the value of the constant will be defined by the first instance of the class:
class A {
public:
A(int param)
{
static const int MY_CONST = param;
cerr << "param: " << param << " const: " << MY_CONST << endl;
};
};
int main()
{
A a1(1);
A a2(2);
return 0;
}
output:
param: 1 const: 1
param: 2 const: 1
// Why not declare this globally?
By only seeing an abridged code fragment, we can only guess. It's typically good practice to put your variables in the narrowest scope possible. After all, everything could be global - we just choose to encapsulate things.
Perhaps the global constants are actually used in a lot of places, whereas the local constant is only used in that local function.
but what is gained by using static?
Probably just consistency. If you're just used to typing your constant values like:
static const T val = ddd;
everywhere, why change when you do it locally? There isn't an advantage or disadvantage of static for creating constant numbers.
static variables are literally static: they are allocated in same place as global variables. Plain local variables are allocated every time function is called on stack. If function is called n times recursively, there are n local variables. Static variable initialized only once. After it has been initialized, there is be only one instance of static variable. So static const local variable is used because of performance reasons.
Variables should have as narrow scope as possible to avoid unnecessary coupling. That's why this variable is local.
This looks like an attempt at premature optimization. Allegedly someone who created the code believed that by using static double variable they will save on creating the variable every time the function is entered.
However, since compilers are not morons, in practice it doesn't matter at all. Optimizing compilers will replace the variable with access to pre-allocated and initialized memory regardless, static or no static.
According to the OP's Code:
#includes...
static const int GLOBAL_CONST1 = 100;
static const double GLOBAL_CONST2 = 1.0;
SomeClass::SomeClass()
:
theDataMember1 (),
theDataMember2 (),
...
{
static const double SOME_VAR = 0.01; // Why not declare this globally?
theDataMember1 = SomeIncludedClass(SOME_VAR);
}
One has to take into consideration a few things:
Data Storage Unit - Storage Class Specifier
Data Storage Duration - Minimum Life Of Data
Scope Visibility - Where The Data Unit Is Visible.
Here is an excerpt:
Global objects and objects in a namespace scope, static data members of a class, and local static objects in functions reside static storage duration. An object with static storage duration resides in the same memory address throughout the program's execution. Every such object is constructed only once during the lifetime of the program. By default, static data is initialized to binary zeros. Static objects with a nontrivial constructor or an explicit dynamic initializer undergo a second initialization phase called dynamic initialization.
The scope of an object declared static in a function is restricted to that function. Objects with static storage duration appear in the following examples:
int num=0; //global variables have static storage
extern int x; //also global, defined in a separate translation unit
int func()
{
static int calls; //local static. initialized to 0 by default
x=calls;
return ++calls;
}
class C
{
private:
static bool b;
};
namespace NS
{
std::string str; //str has static storage
}
The extern Storage Class Specifier
The extern specifier can be applied only to the names of objects and to functions. The extern specifier cannot be used in the declaration of class members or function parameters. Identifiers declared extern have external linkage, meaning they are visible from all translation units of the same program.
A name declared in a namespace scope without a storage-class-specifier has external linkage unless it has internal linkage because of a previous declaration and provided it is not declared const. Objects declared const and not explicitly declared extern have internal linkage, meaning they are visible only from the translation unit in which they are declared.
Notice that the extern keyword is overloaded. It can also be used in explicit-instantiations of templates and in and linkage-specifications, but it is not a storage-class-specifier in such contexts.
The thread_local Storage Duration
The thread_local specifier indicates that the named object or reference has thread storage duration. thread_local shall be applied only to the names of objects or references of namespace scope and to the names of objects or references of block scope that also specify static as their storage class. The thread_local storage class is a new C++09 feature. It's discussed in detail here.
that can be found at this site: C++ Reference Guide | Static Storage Duration
The OP had stated and asked this:
I am working with a class whose constructor declares and initializes a static const variable in the implementation. This is not a data member of the class. I understand the use of const in this context, but what is gained by using static?
I understand that the static const global constants are shared by all instances of the class. Does that also happen with the variable inside the constructor?
Also, why would this not be defined at the Global scope, like the other two? That's where I would normally define my constants.
To answer his/her questions based on the excerpt above and from my own intuition:
their first question:
"What is gained by using static?" static data storage units have automatic initialization. They are created only once and reside in that same memory address or allocation unit.
their second question:
"Does that also happen with the variable inside the constructor?" Yes & No - Yes there is a single instance of this variable upon construction and initialization in the static storage memory unit, but no this is not visible to every instance of the class; it is only local to the Constructor of this class because of scope visibility.
their final question:
"Also, why would this not be defined at the Global scope, like the other two?" This particular variable depending on intention of use might only be used in the initialization of another object. One of the benefits of this maybe to not having to use a stack variable, and is only visible to this class' constructor. So when this constructor is called ctor this static const variable is created and initialize only once per construction and once this class object's constructor goes out of scope this static const variable is no longer visible by any other function or member of this class, or any other translation unit that is outside the visibility of this scope.
There is no definitive answer, however I tried to provide as much insight as I can in regards to the OPs questions, and tried to answer them to the best of my abilities. Some of the things that can vary are the intentions of the programmer and the context in which these memory allocations units are, declared, defined, initialized and then used.
struct A
{
static void f();
};
static void A::f() {} //illegal
Why's this not allowed? Am asking this because the rule seems inconsistent with other keywords.
You must put constexpr on both.
You can put inline on both, but you can also omit one of them. This is useful that you can omit inline in class definition, which is not important information of the interface.
But the rules for static on class members doesn't really make sense. Shouldn't it be consistent with constexpr?
I know static means internal linkage for namespace-scope functions, and this partly explains the current shape. But isn't distinguishing between free functions and class member functions having no ambiguity in namespace scope? For example, if you write static void A::f() {} it's unambiguous that you're defining a member function of A, if A is a class name.
The static in class have other meaning the static in a global or namespace.
when you declared symbol as static in the class, you don't want it to be a global static.
1. static member
In the class it is mean the symbol is class related not object related, means for member variable, there is only one instance for all the objects, and for function, it doesn't have access to non static members, which are object oriented. .
2. static global
In global scope, the static indicate the object or function is local only, and can't be exported (like using extern) to other files. in addition it let you use same name in other file for other variable. so if it located in header file, any file including the header, will have different instance of the symbol.
Therefore if you were allowed to use it in the global scope for a member, then there was an ambiguity.
We can have anonymous namespaces (namespace with no name). They are directly usable in the same program and are used for declaring unique identifiers. It is said that it avoids making global static variable.My question is if it is not static then why default value is zero?
As these question has been asked before but it is not clear at all C++ anonymous namespace: Variables initialized to 0?
#include<iostream>
using namespace std;
namespace
{
int x; // Here x should have garbage value according to definition of anonymous namespace
}
int main()
{
cout << x << endl;// But x is throwing zero why?
}
The anonymous namespace doesn't really prevent names from becoming global names! In fact, a compiler may create object files which define the symbols as global symbols. However, the anonymous namespace basically hides these global names away with a name which can only be referred to from one translation unit.
The zero initialization applies to all objects with static storage duration. All variables at namespace level, including the anonymous namespace and function local static variable have static storage duration unless they are declared thread_local.
I think you incorrectly understand the phrase
It is said that it avoids making global static variable
or the phrase itself is confusing.
In this phrase word static means internal linkage. For example if you will write
namespace N // named namespace
{
static int x;
}
then variable x will have internal linkage. it will not be visible outside the compilation unit where it is defined. Or each module that will contain this definition will have a separate object with name x.
To achieve the same effect you could place its definition in an unnamed namespace. In this case according to the C++ 2011 Standard it will also have the internal linkage.
namespace // unnamed namespace
{
int x;
}
At the same time any object defined in a namespace has static storage duration. It means that it will be initialized. For fundamental scalar types the initialization is the zero initialization.
I think I hvae a fundamental misunderstanding of namespace and/or static variable. But I have tried this test code (typed by hand, forgive typos)
test.h:
namespace test{
static int testNum=5;
void setNum(int value);
}
main.cpp:
#include <test.h>
int test::setNum(int value){
testNum=value;
}
int main(){
test::setNum(9);
cout<<test::testNum;
}
when I run this I get the value 5, not 9 as I would have expected. It seems almost as if I have two instances of the testNum variable, but that seems to be the exact opposite of what static should be doing. I'm guessing I've made a mistake in assuming that these features were identical to their java equvilants somehow...
I also get an error stating that testNum is declared multuple times if I remove the static from my declaration of testNum, could someone explain why that is the case as well?
Thank you
First, your misunderstanding has nothing to do with namespaces, it's only about static. For the rest of this answer I'm going to refer to simply testNum because the fact it's in a namespace is irrelevant.
I'm also assuming you have another file, probably called test.cpp, which also includes test.h and defines the setNum function.
When a variable or function at namespace-scope (i.e. not a class member or local to a function) is declared static it means the entity's name is internal to that file. Formally it has "internal linkage", meaning it can't be referred to by name or linked to from other files (it can be indirectly referred to through a pointer or by passing it as an argument to another function.) That means if several files define static int testNum then each file has its own internal variable with that name, distinct from the testNum in every other file (in fact one file could have static int testnum and another could have static double testnum and another static char* testNum, they'd all be distinct and internal to each file.) If you put a definition like that in header then every file that includes the header has its own testNum.
So with static on your variable in a header you have a different variable called testNum in every file that includes test.h. That means if you set testNum in one file and call a function in a different file which uses testNum it refers to a different variable, which just happens to have the same name.
Because of this, declaring non-const static variables in headers is almost always wrong.
Without static you would have a definition of the testNum variable in every file that includes test.h, which is not allowed: every entity must be defined once and once only in your program. The way to solve that is to declare the variable in the header, but not define it, which you do by telling the compiler the variable is extern:
extern int testNum; // N.B. no "= 1" here
That tells the compiler there is a variable with "external linkage" called testNum, so when code refers to testNum it will always mean the same variable (not some name with internal linakge that is a different entity in every file.) After declaring an extern variable it is your responsibility to ensure there is exactly one definition provided somewhere in the program, so in exactly one file (i.e. not in a header that gets included in multiple files) you define it:
int testNum = 1;
static at namespace scope is a misnomer, and shouldn't be used. It
means simply that the entity declared static has internal name binding;
in other words, that the same name in other translation units will refer
to a different entity, and in the case of variable definitions, that
there will be a separate instance of the variable in each translation
unit. It has no effect on lifetime. (All variables declared or
defined at namespace scope have static lifetime.)
static at namespace scope is also deprecated. Don't use it.
With regards to declaring a variable in a header: prefix it with
extern, and not static. If a variable is declared extern, and
there is no initialization, the declaration is not a definition. Of
course, in this case, you must provide a definition somewhere (in a
single source file). Something along the lines of:
extern int testNum = 5;
int testNum = 5;
int testNum; // implicitly initialized with 0.
EDIT:
To clarify somewhat: there is some confusion here between lifetime and
name binding:
an object has a lifetime (auto, static or dynamic—or temporary, or exception), and
a name is bound to an entity; if the name is declared to be a variable, the entity is an object.
Do not confuse the keyword static with static lifetime. (Functions
can be static, but functions have no defined lifetime in C++; they're
just there.)
The rules regarding these are not very orthognal. Basically, with
regards to lifetime:
all variables declared at namespace scope have static lifetime, always,
variables declared at local scope have auto lifetime unless they are declared static, and
variables declared at class scope have the lifetime of the class object which contains them, unless they are declared static.
regards to lifetime.
Objects with static lifetime come into being sometime before main, and
live until after you return from main.
With regards to name binding:
variables declared at namespace scope have external name binding,
unless they are declared static, in which case they have internal
name binding (but this use of static is deprecated), or if they are
const, and are not declared extern,
variables declared at class scope have external name binding, even if they are declared static, and
variables declared at block scope have no binding.
Finally, there is the question of whether a declaration is a definition
or not. If it is a definition, memory is allocated and the object is
(or may be) initialized. If it is not a definition, it simply tells the
compiler that there is a definition somewhere else for the entity
(object) declared in the declaration. In general, a variable
declaration is a definition unless it is declared extern and does
not have an initializer.
You might want to make sure your code actually has problems before you post it asking what's wrong ;)
I copy/pasted and fixed your typos, and manually did the include:
#include <iostream>
using namespace std;
namespace test{
static int testNum=5;
void setNum(int value);
}
void test::setNum(int value){
testNum=value;
}
int main(){
test::setNum(9);
cout<<test::testNum;
}
result:
$ ./a.out
9
What you haven't said is what else is in your program. If you have more than just main.cpp, and include your test.h, then each .cpp file will have its own copy of testNum. If you want them to share then you need all but one to mark it as extern.
Like this.
struct some_struct
{
// Other fields
.....
__thread int tl;
}
I'm trying to do that but the compiler is giving me this error.
./cv.h:16:2: error: '__thread' is only allowed on variable declarations
__thread int tl;
In C and C++, thread-local storage applies to static variables or to variables with external linkage only.
Local (automatic) variables are usually created on the stack and therefore are specific to the thread that executes the code, but global and static variables are shared among all threads since they reside in the data or BSS segment. TLS provides a mechanism to make those global variables local to the thread and that's what the __thread keyword achieves - it instructs the compiler to create a separate copy of the variable in each thread while lexically it remains a global or static one (e.g., it can be accessed by different functions called within the same thread of execution).
Non-static class members and structure members are placed where the object (class or structure) is allocated - either on the stack if an automatic variable is declared or on the heap if new or malloc() is used. Either way, each thread receives a unique storage location for the variable and __thread is just not applicable in this case, hence the compiler error you get.
gcc imposes the following restrictions on the use of __thread:
The __thread specifier may be applied to any global, file-scoped static, function-scoped static, or static data member of a class. It may not be applied to block-scoped automatic or non-static data member.
The __thread modifier is supported by multiple compiler. It is not inconceivable that the exact restrictions vary somewhat from compiler to compiler.
You should change __thread int tl; to thread_local static int tl;
C11 standard Section 6.7.1 Paragraph 2
At most, one storage-class specifier may be given in the declaration specifiers in a
declaration, except that _Thread_local may appear with static or extern.120)
C11 standard Section 6.7.1 Paragraph 3
In the declaration of an object with block scope, if the declaration specifiers include
_Thread_local, they shall also include either static or extern. If
_Thread_local appears in any declaration of an object, it shall be present in every
declaration of that object.
According to the old Petzold book 'Programming Windows' (page 1241) you mark a variable as thread local by using the keywords: __declspec (thread).
So for instance:
__declspec (thread) int iGlobal = 1;
I doubt this could be done in a class though. You can also make the variable static too.
[edit] just realized you are probably not running on windows... So I guess for anyone who needs an windows answer, this may be relevant.
Write this way:
template <class T> struct S {
thread_local static int tlm;
};
template <> thread_local int S<float>::tlm = 0; // "static" does not appear here
as stated in https://en.cppreference.com/w/cpp/language/storage_duration
You can also specify the struct itself as thread local. For example;
#include <pthread.h>
thread_local struct gl_i_t{
int a;
int b;
}GL_i_t;
Then you can use GL_i_t variables inside thread.
For C this makes not much sense, static (= global) members are only a feature of C++. And so the new C11 standard (that introduces _Thread_local) doesn't allow it. These beast are allowed basically everywhere were a variable with static storage duration is allowed.
For C++ this could make sense inside a class as analogous to a static member, but if this is allowed by C++11 I have no idea.
You can use thread_local for static members of a class or structure in C++.
struct some_struct
{
// Other fields
.....
thread_local static int tl;
}
This should be fine. So some_struct::tl could have different values in different threads.
If you want to define it, you have to add thread_local again:
thread_local int some_struct::tl = 10;