Declaring a global variable in a non-member function - c++

Can I declare a global variable inside a non-member function?
Or in other words, a static equivalent for a non-member function?
And I'd like the variable to not be const - e.g. modifiable...

You can declare a global variable inside a function:
void f() {
extern int i;
}
But you'll also need to define it in the surrounding namespace, if you want to use it.
Being global, the definition doesn't have to be the same translation unit, but is subject to the One Definition Rule.
If, as indicated in the comments, you actually want a persistent local variable, initialised the first time the function is called, then that's exactly how a local static variable behaves:
void f() {
static int i = whatever(); // initialised the first time
i = something_else(); // the new value is preserved for next time
}

Can I declare a global variable inside a non-member function?
You can provide a declaration for a namespace level global variable inside a function. But I have the feeling that you are looking for something else and did not get the wording quite right:
Or in other words, a static equivalent for a non-member function?
You can declare (and define) a local static variable in a function. The lifetime of which will extend beyond the execution of the function (i.e. the variable will be there for the next function execution and so on).
int nextValue() {
static int counter = 0;
return ++counter;
}
Note that this is not a global, as global implies accessibility from any context and this variable is only accessible within nextValue.
And I'd like the variable to not be const - e.g. modifiable...
This is completely orthogonal to where you declare/define a variable.

Related

In C++, what is the benefit of defining a Static Const variable within a member function?

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.

boost::lexical_cast produces undefined reference for static member variable [duplicate]

Why must static data member initialization be outside the class?
class X
{
public:
int normalValue = 5; //NSDMI
static int i;
};
int X::i = 0;
Why is the static data member (here "i") only a declaration, not a definition?
It's important to distinguish the initializer which says what its initial value is, and the definition. This modified code is valid, with the initializer in the class definition:
class X
{
public:
int normalValue = 5;
static const int i = 0; // declaration, with initializer
};
const int X::i; // definition
i.e. What must be outside the class is a definition, not the initialization.
That's because a variable must have an address in memory (unless it's only used in limited situations, such as in compile-time constant expressions.)
A non-static member variable exists inside the object it is a member of, so its address depends on the address of the object that contains it. Every time you create a new X you also create a new X::normalValue variable. The non-static data member's lifetime begins with the class' constructor. NSDMI syntax doesn't have anything to do with the variable's address in memory, it just allows you to provide an initial value in one place, instead of repeating it in every constructor with an explicit constructor initializer list.
On the other hand, a static member variable is not contained within an instance of the class, it exists independently of any single instance and exists from the start of the program, at a fixed address. In order for a static member variable (or any other global object) to get a unique address the linker must see exactly one definition of the static variable, in exactly one object file, and assign it an address.
Because a static variable needs exactly one definition in exactly one object file, it doesn't make sense to allow that definition to be provided in the class, since class definitions typically exist in header files and are included in multiple object files. So although you can provide an initializer in the class, you still need to define the static data member somewhere.
You can also look at it like declaring an extern variable:
namespace X {
extern int i;
}
This declares the variable, but there must be a definition somewhere in the program:
int X::i = 0;
You need to supply a separate definition for a static data member (if its odr-used, as defined in C++11) simply because that definition shall reside somewhere - in one and only one translation unit. Static class data members are basically global objects (global variables) declared in class scope. The compiler wants you to choose a specific translation unit that will hold the actual "body" of each global object. It is you who has to decide which translation unit to place the actual object to.
"static" class member is like a globally allocated variable (it is not related to the single class instance), so it must reside in some object file (and to be declared in the ".cpp" file) as a symbol just like any global variable.
Simple class member (non-static) resides in the memory block allocated for the class instance.
The simple reason is because classes are usually declared in header files, which often are included in multiple cpp files. Static data members have external linkage and must be declared in exactly one translation unit which makes them unfit for being defined inside a class.
As juanchopanza points out the following is allowed:
struct A
{
const static int i = 1;
};
However, this is only a declaration not a definition. You still need to define it if you are going to use i's address somewhere.
For example:
f(int);
g(int&);
X<A::i> x; // Okay without definition for template arguments
char a[A::i]; // Okay without definition, just using value as constant expression
&A::i; // Need a definition because I'm taking the address
f(A::i); // Okay without definition for pass by value
g(A::i); // Need a definition with pass by reference
Bear in mind that is is possible to initialize the static data member at the point of declaration if it is of const integral type of const enumeration type:
From the C++03 standard, §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 (5.19)
struct Foo {
static const int j = 42; // OK
};
When the compiler generate binary code from a unit (extreme simplification: a cpp file and all its included headers) it will emit a symbol for the static variable and eventually initialization code for that variable.
It is okay for a static variable symbol to be declared in multiple units, but it is not okay for it to be initialized multiple times.
So you must make sure that the initialization code is only emitted for a single unit.
This mean that the static variable must be defined in exactly one unit.
Static Data Member
#include<iostream.h>
#include<conio.h>
class static_var
{
static int count; //static member of class
public :
void incr_staticvar()
{
count++;
}
void outputc()
{
cout<<"Value of Static variable Count :- "<<count<<endl;
}
};
int static_var::count;
void main()
{
clrscr();
static_var obj1,obj2,obj3,obj4;
obj1.incr_staticvar();
obj2.incr_staticvar();
obj3.incr_staticvar();
obj4.incr_staticvar();
cout<<"\nAfter Increment of static variable by Four Different objects is :-\n";
obj1.outputc ( );
obj2.outputc ( );
obj3.outputc ( );
obj4.outputc ( );
getch();
}

Static Data Member Initialization

Why must static data member initialization be outside the class?
class X
{
public:
int normalValue = 5; //NSDMI
static int i;
};
int X::i = 0;
Why is the static data member (here "i") only a declaration, not a definition?
It's important to distinguish the initializer which says what its initial value is, and the definition. This modified code is valid, with the initializer in the class definition:
class X
{
public:
int normalValue = 5;
static const int i = 0; // declaration, with initializer
};
const int X::i; // definition
i.e. What must be outside the class is a definition, not the initialization.
That's because a variable must have an address in memory (unless it's only used in limited situations, such as in compile-time constant expressions.)
A non-static member variable exists inside the object it is a member of, so its address depends on the address of the object that contains it. Every time you create a new X you also create a new X::normalValue variable. The non-static data member's lifetime begins with the class' constructor. NSDMI syntax doesn't have anything to do with the variable's address in memory, it just allows you to provide an initial value in one place, instead of repeating it in every constructor with an explicit constructor initializer list.
On the other hand, a static member variable is not contained within an instance of the class, it exists independently of any single instance and exists from the start of the program, at a fixed address. In order for a static member variable (or any other global object) to get a unique address the linker must see exactly one definition of the static variable, in exactly one object file, and assign it an address.
Because a static variable needs exactly one definition in exactly one object file, it doesn't make sense to allow that definition to be provided in the class, since class definitions typically exist in header files and are included in multiple object files. So although you can provide an initializer in the class, you still need to define the static data member somewhere.
You can also look at it like declaring an extern variable:
namespace X {
extern int i;
}
This declares the variable, but there must be a definition somewhere in the program:
int X::i = 0;
You need to supply a separate definition for a static data member (if its odr-used, as defined in C++11) simply because that definition shall reside somewhere - in one and only one translation unit. Static class data members are basically global objects (global variables) declared in class scope. The compiler wants you to choose a specific translation unit that will hold the actual "body" of each global object. It is you who has to decide which translation unit to place the actual object to.
"static" class member is like a globally allocated variable (it is not related to the single class instance), so it must reside in some object file (and to be declared in the ".cpp" file) as a symbol just like any global variable.
Simple class member (non-static) resides in the memory block allocated for the class instance.
The simple reason is because classes are usually declared in header files, which often are included in multiple cpp files. Static data members have external linkage and must be declared in exactly one translation unit which makes them unfit for being defined inside a class.
As juanchopanza points out the following is allowed:
struct A
{
const static int i = 1;
};
However, this is only a declaration not a definition. You still need to define it if you are going to use i's address somewhere.
For example:
f(int);
g(int&);
X<A::i> x; // Okay without definition for template arguments
char a[A::i]; // Okay without definition, just using value as constant expression
&A::i; // Need a definition because I'm taking the address
f(A::i); // Okay without definition for pass by value
g(A::i); // Need a definition with pass by reference
Bear in mind that is is possible to initialize the static data member at the point of declaration if it is of const integral type of const enumeration type:
From the C++03 standard, §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 (5.19)
struct Foo {
static const int j = 42; // OK
};
When the compiler generate binary code from a unit (extreme simplification: a cpp file and all its included headers) it will emit a symbol for the static variable and eventually initialization code for that variable.
It is okay for a static variable symbol to be declared in multiple units, but it is not okay for it to be initialized multiple times.
So you must make sure that the initialization code is only emitted for a single unit.
This mean that the static variable must be defined in exactly one unit.
Static Data Member
#include<iostream.h>
#include<conio.h>
class static_var
{
static int count; //static member of class
public :
void incr_staticvar()
{
count++;
}
void outputc()
{
cout<<"Value of Static variable Count :- "<<count<<endl;
}
};
int static_var::count;
void main()
{
clrscr();
static_var obj1,obj2,obj3,obj4;
obj1.incr_staticvar();
obj2.incr_staticvar();
obj3.incr_staticvar();
obj4.incr_staticvar();
cout<<"\nAfter Increment of static variable by Four Different objects is :-\n";
obj1.outputc ( );
obj2.outputc ( );
obj3.outputc ( );
obj4.outputc ( );
getch();
}

Difference between static variable inside and outside of a function?

static int count;
int main()
{
static int count;
}
Is there any difference between static variables declared inside and outside any function?
(I mean the scope and visibility of the variable count)
Your first count is only accessible within the module (code in that file). Your second count is only accessible within main.
When you declare outside of method it will be available to all static method functions written after its declaration. While declaring static variable in method will be accessible by only that method.
There's also a difference in dynamic initialization of globals (see here). To summarize, if you had:
static int count = bar();
int main ()
{
static int count = foo ();
}
The call to 'foo' will take place when main is executed, but the standard (C++ '03) doesn't require a call to 'bar' at all!

What exactly does "static" mean when declaring "global" variables in C++?

This is an expansion of the scope of a previous question of mine.
What exactly is "static", how is it used, and what is the purpose of using "static" when dealing with C++?
Thanks.
It means that the variable is local to a translation unit (simply put, to a single source file), and cannot be accessed from outside it. This use of static is in fact deprecated in the current C++ Standard - instead you are supposed to use anonymous namespaces:
static int x = 0;
should be:
namespace {
int x = 0;
}
The keyword static has different meanings in C++, depending on the context.
When declaring a free function or a global variable it means that the function is not to be available outside of this single translation unit:
// test.cpp
static int a = 1;
static void foo() {}
If the result of compiling that translation unit is linked with a different translation unit containing symbols a and foo it will not break the One Definition Rule, as in this particular translation unit a and foo are private symbols. This use has been obsoleted by unnamed namespaces.
// test2.cpp
namespace {
static int a = 1;
static void foo() {}
}
When declaring a local variable within a function it means that the lifetime of the variable will extend from the first call to the function to the end of the program, and not only for the duration of the call:
int foo() {
static int counter = 0;
return ++counter;
}
int main() {
for ( int i = 0; i < 10; ++i ) {
std::cout << foo() << std::endl;
}
}
In the previous code, counter is initialized once when foo is called for the first time, but the variable will outlive the function and keep the value across different function calls. The previous code will print "1 2 3 4... 10". If the variable was not declared static then the output would be "1 1 1... 1".
Within a class scope, static means that the member is a member of the class, and not of a particular instance. This use is equivalent to the use in your other question: usage of that particular member is not bound to any specific object.
struct test {
int x;
static int y;
};
int test::y; // need to define it in one translation unit
int main() {
// test::x = 5; // !error cannot access a non-static member variable
// without an instance
test::y = 5; // ok
test t, other;
t.x = 10; // ok
t.y = 15; // ok, the standard allows calling a static member through
// an instance, but this is the same as test::y
}
In this case, the member x is a non-static member attribute, and as such there is a different x for each instance of the class. In the sample program t.x and other.x refer to different integers. On the other hand y is static and thus there is a single instance of test::y in the program. Even if the standard allows to call t.y and other.y both uses refer to the same variable. The same goes with member methods. If they are static they are class-level methods and can be called without an instance, while if they are non-static they are applied to a concrete instance and the a.b or a->b syntax must be used.
This use of static is similar to the use of the same keyword in Java, while the other two are not present in that language. There is one use of the keyword in Java that is not present in C++, and that is the use of static class initializers (a block of code at class level surrounded by static { ... }). In Java that block of code will be executed when the class is loaded and only once. Initialization of static member variables in C++ must be done in the initializer of the variable definition.
This stuff seems to be fairly well covered here.
But to paraphrase, there are 2 uses in C
Prevent the use of a global variable outside the scope of the file that defines it.
Allow local variables within a function to persist accross invocations of the function, as in
int getNextId()
{
static int id = 0;
return id++;
}
C++ inherits both of these, and adds two uses of its own.
static member variables: Variables that are "shared" accross all instances of a class, and can also be accesses without reference to an instance of the class. Shared seems like the wrong word, but in essence I beleive that the result is that any reference to a static member variable references the same memory location.
static methods: Methods that can be called without reference to a specific instance of the class that defines it.
Static basically means that a variable is tied to the lifetime of the program and not of any given function or class instance. When should you use it? Don't. What is the purpose? Debugging data, mostly.
Generally, in C++, if you find yourself using static data, you've done it wrong. There are times when it's appropriate, but they're very rare.
When static is used in a class in C++, it means more or less the same thing that it does in Java. For variables it means that one one instance of the variable exists for all classes and for functions, it means that the function does not implicitly access the this pointer at all.
In C and C++ when static is used for a global variable or function, then it means that the variable may only be referenced in the current C or C++ file. In other words, the compiler must not generate any relocation symbols for the variable or function.
When static is used next to a variable in a local function, it means that the variable does not go out of scope but will retain its value from function-call to function-call. The variable become effectively a global variable that can only be accessed from the given function.
Static class members are data and functions that are associated with the class itself, rather than with the objects of the class.
In the following example, class Fred has a static data member x_ and an instance data member y_. There is only one copy of Fred::x_ regardless of how many Fred objects are created (including no Fred objects), but there is one y_ per Fred object. Thus x_ is said to be associated with the class and y_ is said to be associated with an individual object of the class. Similarly class Fred has a static member function f() and an instance member function g().
class Fred {
public:
static void f() throw(); <-- 1
void g() throw(); <-- 2
protected:
static int x_; <-- 3
int y_; <-- 4
};
(1) Member function associated with the class
(2) Member function associated with an individual object of the class
(3) Data member associated with the class
(4) Data member associated with an individual object of the class
Usage:
When you want to keep tract of the number of instances of a class created you use static variable. For example in a 'Car' class each Car instance may have a unique serial number(_y in this case) and the company may want to keep track of the number of cars produced(_x in this case).