static object initializer C++ [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
file scope and static floats
What are static variables?
Here is a code from a book.
class X
{
int i;
public:
X(int ii = 0) : i(ii) {cout<<i<<endl;} // Default
~X() { cout << "X::~X()" << endl; }
};
void f()
{
static X x1(47);
static X x2; // Default constructor required
}
int main()
{
f();
return 0;
}
My question is why would I like to declare an object as static like in function f()? What would happen if I did not declare x1 and x2 as static?

For this code it makes no difference to the observable behavior of the program.
Change main to call f twice instead of only once, and observe the difference -- if the variables are static then only one pair of X objects is ever created (the first time f is called), whereas if they're not static then one pair of objects is created per call.
Alternatively, change main to print something after calling f. Then observe that with static, the X objects are destroyed after main prints (the static objects live until the end of the program), whereas without static the objects are destroyed before main prints (automatic objects only live until exit from their scope, in this case the function f).

The first time the function f() is hit the statics will be initialized (lazy loading). Had they not been declared static then they would be local variables and recreated every time you called function f().
All calls to f() will result in using the same x1 and x2.

The difference between
int f()
{
int i = 0;
++i;
return i;
}
int f2()
{
static int i = 0;
++i;
return i;
}
int main()
{
for (int i = 0; i < 10; ++i) { cout << f1() << ' ' << f2() << endl; }
}
Is that f1 will always make a new local variable i and set it to zero then increment it, while f2 will create a static local variable i and initialize it to zero once and then each call it increments it from the previous call value.

Here is some code to test what does a static object within a function mean:
#include <iostream>
using namespace std;
class A {
public:
void increase() {
static int b = 0;
b++;
cout << "A::increase: " << b << endl;
}
};
int main() {
A a;
a.increase();
a.increase();
a.increase();
return 0;
}
And the output is:
A::increase: 1
A::increase: 2
A::increase: 3
Notice the value of b is kept between function calls? Here is the example on ideone so that you can play with it.

Related

Why is a C++ lambda life cycle bound to the smallest block scope?

In the following example program, I would expect the counter to reset at the beginning of each cycle:
#include <iostream>
#include <functional>
void run_lambda(std::function<void()> fun){ fun(); fun(); }
int main(){
for(int i = 0; i < 3 ; ++i){
run_lambda([i](){
static int testVal = 0;
std::cout << "value[" << i << "]:" << testVal << std::endl;
++testVal;
});
}
return 0;
}
Instead the output is:
value[0]:0
value[0]:1
value[1]:2
value[1]:3
value[2]:4
value[2]:5
According to this answer:
The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression.
In my understanding this means, that the lambda object life cycle is bound to the loops block scope, thus the static variable is not resetting at the start of the loop.
Is there a specific reason for this? Intuitively one would think that a lambda expression is essentially a temporary object, and as such in this example it would cease to exist after the statement.
Your code is basically equivalent to:
#include <iostream>
#include <functional>
struct lambda
{
lambda(int i): i(i) {}
int i;
void operator()()
{
static int testVal = 0;
std::cout << "value[" << i << "]:" << testVal << std::endl;
++testVal;
}
};
void run_lambda(std::function<void()> fun){ fun(); fun(); }
int main(){
for(int i = 0; i < 3 ; ++i){
lambda l{i};
run_lambda(l);
}
return 0;
}
Whilst each iteration of the loop does indeed create a new lambda object each object is an instance of the same class and therefore shares the same static variables.
The statement you're quoting is saying that the type is declared inside the scope where the lambda is declared. It isn't saying that each time the code enters that scope a new type is created (c++ doesn't have dynamic types like that).

Why isn't the static variable getting modified

I'm creating a static variable 'a' inside a member function getobj() and returning it by reference and capture the reference in b. And I modify the same static variable 'a' in another member function mod(). When I print b, I should be expecting '2' right? Why isn't the static variable 'a' not modified to 2?
#include <iostream>
using namespace std;
class Test {
public:
int& getobj() {
static int a = 1;
return a;
}
void mod() {
static int a = 2;
}
};
int main(int arc, char* args[]) {
Test t;
int &b = t.getobj();
cout << "printing b first time and its value is expected : " << b << endl;
t.mod();
cout << "printing b second time after modifying and its value has not changed : " << b << endl;
return 0;
}
Output observed is
printing b first time and its value is expected : 1
printing b second time after modifying and its value has not changed : 1
The variable a in getobj() and the variable a in mod() are in different scope and are different things.
Therefore, modification to a in mod() won't affect a in getobj().
You could achieve your aim with the following piece of computational devilry:
void mod() {
static int& a = getobj();
a = 2;
}
Currently you have two different ints, both with static storage. Changing one will not change the other.
But did you want to use a class member variable instead (which is the normal thing to do), perhaps even without static storage duration?

understanding static member function and variable and destructor

#include<iostream>
using namespace std;
class Test
{
public:
static int Retr(); // Static member function
//~Test(); // Test destructor
Test(); // Default constructor
private:
static int count; // Static member variable
int i;
};
int Test::count = 0; // Initialization
int main()
{
Test obj;
cout << Test::Retr() << endl;
// The result should be 1 but prints two
return 0;
}
Test::Test() : i(1) { Retr(); }
int Test::Retr()
{
return ++count;
}
/*
Test::~Test()
{
count--;
}
*/
I'm practising about usage of static member function and variable. I have a static member function that counts and returns how many objects are constructed. It should show 1 for this example but it shows 2. I don't understand why it happens. However, the destructor decreases the counter end of scope for every constructed objects. Doesn't it? So, the result using with destructor should be 0. But, I can't get the expected results. Could someone explain?
Edited what about not working of destructor ? Solved
#include<iostream>
using namespace std;
class Test
{
public:
static int Retr(); // Static member function
~Test(); // Test destructor
Test(); // Default constructor
private:
static int count; // Static member variable
int i;
};
int Test::count = 0; // Initialization
int main()
{
Test obj[2];
cout << Test::Retr() << endl;
// The result should be 0 because of destructor but prints 2
return 0;
}
Test::Test() : i(1) { ++count; }
int Test::Retr()
{
return count;
}
Test::~Test()
{
--count;
cout << Test::Retr() << endl;
}
Test::Test() : i(1) { Retr(); }
When you have created an object, It also calls retr() function. Thats increments count; And again you call retr() to show..
Your destructor is working.Call Test::Retr() to check count after destruction.
Test::~Test()
{
--count;
cout << Test::Retr() << endl;
}
First things first, you need to understand what is a static member function.
Static members of a class are not associated with the objects of the class: they are independent objects with static storage duration or regular functions defined in namespace scope, only once in the program.
So your entire program will only have one instance of count (Which is initialized to 0)
Let us look at the code in the main function, you're creating an object of the class Test. Hence the constructor gets called, which inturn calls the static int Retr() function. Hence count is now 1. Now,
cout << Test::Retr() << endl;
Calls Retr() again, hence it increments count and returns the value. Hence 2 is returned.
As far as the destructor is concerned, it is not called before the cout. It will be called only when obj goes out of scope, which will happen only when the main function is completed.
When you are creating
Test obj;
It calls the constructor and increments 1
and again you are calling
Test::retr()
It also increments 1.
If you want to check the behavior of your class you can add additional function as
void testFunction(){
Test obj[2];
std::cout << Test::Retr() << std::endl; // count became 3
}
int main(){
testFunction();
// Obj destructed here count became 1
std::cout << Test::Retr() << std::endl;
// It will again increment and count will be 2
}

Static short reference yields an error in recursive function

Here's the whole source:
#include <iostream>
void recursion(static short &di);
using namespace std;
int main()
{
short pi = 1;
for(pi; pi > 0; pi++)
{
cout << "Hi, pi!" << "\n";
recursion(pi);
}
}
void recursion(static short &di)
{
di++;
if(di < 20)
{
return;
}
else
{
cout << di << "\n";
}
}
For some reason it works fine when the 16-bit container isn't static, but I want it to be static, and it gives the following error:
main.cpp:2:29: error: storage class specifiers invalid in parameter declarations
void recursion(static short di);
^
main.cpp:2:29: error: storage class specified for parameter 'di'
main.cpp:14:29: error: storage class specifiers invalid in parameter declarations
void recursion(static short di)
^
main.cpp:14:29: error: storage class specified for parameter 'di'
You can't specify a static storage duration for function parameters.
You can still pass a reference to a static varibale to a function, and the reference will still refer to a static variable.
For example:
int main()
{
static short pi = 1;
// ^^^^^^
for(pi; pi > 0; pi++)
{
cout << "Hi, pi!" << "\n";
recursion(pi);
}
// ...
}
void recursion(short &di)
{
// ...
}
But in your case making pi a static seems rather pointless.
You might not fully understand what a static storage duration means, so I'll take the liberty to explain.
Normally you declare variable without the static qualifier like this:
void foo()
{
int myValue = 42;
}
A varibale declared like this has automatic storage duration; meaning when it "goes out of scope", the object is destroyed. If you were to call foo() 100 times:
int main()
{
for (int i = 0; i < 100; ++i)
foo();
}
...then myValue would be re-initialized 100 times. Normally this is exactly what you want.
Sometimes you want a variable to outlive the scope in which it's declared. To accomplish this, you give it static storage duration, using the static keyword:
void foo()
{
static int myValue = 42;
}
A variable declared this way will be initialized exactly once, before it's first usage, and will continue to live even after its gone out of scope. It will retain it's value until it's been reassigned, until the program ends.
Your code:
int main()
{
short pi = 1;
for(pi; pi > 0; pi++)
{
cout << "Hi, pi!" << "\n";
recursion(pi);
}
}
establishes the pi variable, and then calls recursion a number of times. Here pi does not need static storage duration, because it will never go out of scope during the loop where you call recursion. All you have to do is pass a reference to pi to recursion, and it will behave as you intend.
The error message is quite explicit; you cannot have a static qualifier for a formal argument; you need to declare
void recursion(short &di);
and later to define
void recursion(short &di) {
di++;
if(di < 20)
return;
else
cout << di << "\n";
}

local variables of static member functions

Today we came accross a problem concerning static member functions in an multithreaded environment. The question we asked ourselves and couldn't find a satisfying answer is:
are local varialbes of static member functions static as well?
// header
class A
{
static int test();
}
// implementation
int A::test()
{
int a = rand();
int b = rand();
int c = a + b;
return c;
}
Say you have two threads both calling A::test(). Is it possible that while thread 1 proccesses c = a + b thread 2 enters test() and changes the value of a by assigning the new return value of rand() or in other words do both threads operate an the some memory locations for a, b and c?
No. The stack frames are independent for each thread's invocation of the function, and each gets its own locals. (You do need to be careful if you're accessing actual shared data e.g. static members in the class.)
Unless explicitly declared as static, no they're not. They're on a stack, and each thread has a separate stack.
The storage class of a, b, and c are (implicitly) auto which usually means on the call stack. They don't "inherit" static storage class from the method signature (which is a different meaning of static (yay for grossly overloaded keywords!)).
No, a, b, and c are not static.
Here's a sample that illustrates this:
class Val
{
public:
Val() { cout << "Val" << this << endl; }
~Val() { cout << "~Val" << this << endl; }
int n_;
};
class A
{
public:
static int test()
{
Val a;
a.n_ = rand();
Val b;
b.n_ = rand();
Val c;
c.n_ = a.n_ + b.n_;
return c.n_;
}
};
int main()
{
srand(time(0));
for( int i = 0; i < 5; ++i )
{
cout << "Test = " << A::test() << endl;
}
return 0;
}