Callback function "C style" called from C++ object - c++

I'm learning on the field about callback functions. Thanks to some of you I learned much.
I'm using a C++ instance of an object that must call a callback function: a single function, not a C++ method as the follow:
MyObj *obj = new MyObj();
obj->callback(function);
//callback
void funtion()
{
int i = 10;
...
}
My doubt is the following:
if different instances of MyObj invoke the callback, do they will create different "instances" of "function" with their own local variables? in other words are there different "i = 10" in memory for each object invocation or the risk is that the same "i" is shared?
Thank you

There is no such thing as an "instance" of a function. All local variables of a function, member or free-standing, are placed in the automatic storage area (also known as "on the stack"). These variables stay in the automatic storage area until they are no longer needed because their scope has ended, and then get discarded.
Each thread running your function concurrently will have its own copy of the local variables - in your case, each one will have its own i.
Note that if you want to share a variable among multiple invocations, C++ lets you do that by marking the variable inside the function static:
void funtion()
{
static int i = 10;
...
}
Now all invocations of function share the same variable i. Moreover, the value of i will persist across multiple invocations: for example, if one call sets i to 20 before exiting, and then another call enters the function, the value of i would remain 20, not 10, because the initialization of i is performed only once in the run time of your program.

Related

Is there any purpose of declaring lambda followed by immediately invocation to initialize local variable using its return value?

template<typename T>
static const Metatype* get_metatype() {
static const Metatype* mt = []() {
constexpr size_t name_hash = Metatype::build_hash<T>().name_hash;
auto type = metatype_cache.find(name_hash);
if (type == metatype_cache.end()) {
constexpr Metatype newtype = Metatype::build<T>();
metatype_cache[name_hash] = newtype;
}
return &metatype_cache[name_hash];
}();
return mt;
}
Variable mt initialized by lambda's return value. Why not just extract lambda code and make it part of get_metatype() function then just return value from it? Is this some performance trick or what??
This code from decs https://github.com/vblanco20-1/decs project that i am learning for educational purposes.
The variable mt is declared static, meaning that there is only one instance (with static storage duration) of mt for each T in the program or in each translation unit (depending on whether the function shown is a static function in a class or at namespace scope) and if the function get_metatype<T>() is called multiple times in the program, only the first call reaching mt's declaration will execute mt's initializer and initialize mt. The other calls will simply return the then-fixed value of mt. This is even guaranteed to hold when multiple threads are involved, without the initializer ever being called in two of the threads.
Using a directly-invoked lambda in the initializer allows one to put all the code that should be executed only once to initialize the variable mt in one place inline without having to create a new function for it. If you put the statements inside the lambda directly in the body of get_metatype<T>(), then they would be executed each time the function is called and not only once, and the responsibility of avoiding data races in the initialization when multiple threads are involved would shift to you.
In particular, possible reasons for using the static mt here might be that there are multiple threads and a data race on the construction of the the "metatype" must be avoided, although there would still seem to be a race condition or even a data race on metatype_cache if multiple calls to get_metatype<T>() for different T are made, because the find and the placement into the container are not done atomically.
Or a possible reason could be that the lookup operations into get_metatype take too long to execute each time get_metatype is called, although a static variable is not the best choice for performance optimization either, since it requires thread-safe checks on each call to verify whether mt has already been initialized.
In addition to what #cigien said - a static variable is initialized only once. C++11 and later ensure that initialization is performed in a thread-safe manner. Using a lambda for the initializer ensures that the lambda is called only once. If you were to inline the lambda's code directly in get_metatype(), you would be responsible for manually serializing the code yourself, such as with a mutex.
This is commonly used to initialize a variable that needs to be const, but is also complex to initialize. e.g.
const std::vector<int> v = [] {
std::vector<int> vv;
// ... very complicated logic to initialize vv
// even could be IO, etc ...
return vv;
}();
without doing this, there's no good way to make v const.
However, in your case, the reason for using this technique in the provided example, is so that the static variable mt is not initalized on every call to get_metatype, as pointed out by #walnut, and #Remylebeau.

Pass by reference, child scope only?

I have tried searching on this, since I bet there are questions like these already. However I only get topics about passing by reference in a global setting.
I was wondering about the following;
Variable scope is in this function only and will be cleaned when leaving the scope
void Class::DoSomething(){
String s = "localVariable";
cout << s;
}
If I would change the prior function in the following two functions. Would the scope be also only in the parent function and will the variable memory be freed or do I have to call free()?
void Class::DoSomethingParent(){
String s = "localVariable"; //Local scope only
//This function uses the reference of my variable s.
Class::DoSomethingChild(s);
//Does the prior function do anything special because of the reference,
//so I have to call free(s)?
//Or does the variable still gets freed after leaving the scope of this function?
}
void Class::DoSomethingChild(String& value){
cout << value;
}
Objects with an Automatic Storage Duration in C++ are essentially objects declared within a function block scope, that scope owns and controls the lifetime of such objects created therein. Example:
void function(){
....
String s = "Some Data";
someFuncByReference(s);
....
} //All objects of automatic storage duration owned by this scope are destroyed here...
Irrespective of whether you pass the object by reference or take the address of the object, and pass unto a function. The called function, someFuncByReference still doesn't control the lifetime of s, and should not destruct s1.
This applies to any "function", including, non member-functions, member-functions and function specializations produced by templates. Note that, this is not the same with data members of a class. The lifetimes of class data members are controlled by the constructor and destructor of that class.
1: However, if it does, it must create another one using placement-new.

Any risk of sharing local static variable of a method between instances?

Let's say I create:
class Hello {
public:
int World(int in)
{
static int var = 0; // <<<< This thing here.
if (in >= 0) {
var = in;
} else {
cout << var << endl;
}
}
};
Now, if I do:
Hello A;
Hello B;
A.World(10);
A.World(-1);
B.World(-1);
I'm getting output of "10" followed by another "10". The value of the local variable of a method just crossed over from one instance of a class to another.
It's not surprising - technically methods are just functions with a hidden this parameter, so a static local variable should behave just like in common functions. But is it guaranteed? Is it a behavior enforced by standard, or is it merely a happy byproduct of how the compiler handles methods? In other words - is this behavior safe to use? (...beyond the standard risk of baffling someone unaccustomed...)
Yes. It doesn't matter if the function is a [non-static] member of a class or not, it's guranteed to have only one instance of it's static variables.
Proper technical explanation for such variables is that those are objects with static duration and internal linkage - and thus those names live until program exits, and all instances of this name refer to the same entity.
Just one thing to add to the correct answer. If your class was templated, then the instance of var would only be shared amongst objects of the same instantiation type. So if you had:
template<typename C>
class Hello {
public:
int World(int in)
{
static int var = 0; // <<<< This thing here.
if (in >= 0) {
var = in;
} else {
cout << var << endl;
}
}
};
And then:
Hello<int> A;
Hello<int> B;
Hello<unsigned> C;
A.World(10);
A.World(-1);
B.World(-1);
C.World(-1);
Then the final output would be "0" rather than "10", because the Hello<unsigned> instantiation would have its own copy of var.
If we are talking about the Windows Compiler it's guaranteed
https://msdn.microsoft.com/en-us/library/y5f6w579.aspx
The following example shows a local variable declared static in a member function. The static variable is available to the whole program; all instances of the type share the same copy of the static variable.
They use an example very similar to yours.
I don't know about GCC
Yes, it is guaranteed. Now, to answer the question "Any risk of sharing local static variable of a method between instances?" it might be a bit less straightforward. There might be potential risks in the initialization and utilization of the variable and these risks are specific to variables local to the method (as opposed to class variables).
For the initialization, a relevant part in the standard is 6.7/4 [stmt.dcl]:
Dynamic initialization of a block-scope variable with static storage
duration (3.7.1) or thread storage duration (3.7.2) is performed the
first time control passes through its declaration; such a variable is
considered initialized upon the completion of its initialization. If
the initialization exits by throwing an exception, the initialization
is not complete, so it will be tried again the next time control
enters the declaration. If control enters the declaration concurrently
while the variable is being initialized, the concurrent execution
shall wait for completion of the initialization. If control
re-enters the declaration recursively while the variable is being
initialized, the behavior is undefined.
In the simple cases, everything should work as expected. When the construction and initialization of the variable is more complex, there will be risks specific to this case. For instance, if the constructor throws, it will have the opportunity to throw again on the next call. Another example would be recursive initialization which is undefined behavior.
Another possible risk is the performance of the method. The compiler will need to implement a mechanism to ensure compliant initialization of the variable. This is implementation-dependent and it could very well be a lock to check if the variable is initialized, and that lock could be executed every time the method is called. When that happens, it can have a significant adverse effect on performance.

static var in member function

bool SomeClass::Function( bool thankYou = true )
{
static bool justAbool = false;
// Do something with justAbool;
...
}
I have searched around but I can't find anything about this except globals vars or member functions itself.
What does the above do, i.e. what happens, does justAbool keep its value after leaving the scope? Or does it 'remember' the value when it re-enters the scope?
The variable justAbool is initialized to false only once and it is initialized before the function is entered. The value will be remembered after leaving the scope of the function. It is important to note that the value will also be shared by all instances of SomeClass just like a static member variable. The variable justAbool will not be re-initialized if you create a new instance of your class and then call the function again.
static when applied to a local variable gives that variable static storage duration. This means that the justAbool's lifetime lasts to the end of the program rather than to the end of the invocation of the function. It's scope stays the same, it can only be accessed by name in the function, after the declaration appears.
justAbool will be initialized (using the supplied initializer = false) the first time that the function is called. Thereafter it will retain its previous value, it will not be reinitialized when the function is called again.
Here are some fuller details about storage duration and lifetimes, with references to the standard.
If an object has static storage duration, it means that the storage for the object lasts for the duration of the program (beginning to end). (3.7.1 [basic.stc.static])
As a bool is a type without a non-trivial constructor, its lifetime mirrors that of its storage, i.e. it lives from the beginning to the end of the program. (3.8 [basic.life])
All objects with static storage duration (including local objects) are zero-initialized before any other initialization. (6.7/4 [stmt.decl]) [For local objects with an initializer this is fairly academic because there is no way to read their value before their declaration is reached.]
Local objects of POD type with static storage duration initialized with constant-expressions are initialized before their block is entered, otherwise local objects with static storage duration are initialized when control passes through their declaration. (6.7/4 again)
An implementation is permitter, but not required, to perform early initialization in some situations.
The above function does what it does in the comment // Do something with justAbool;.
On a serious note, yes, the static variable (in this case justAbool) inside a function retains it's value even after returning from the function. It gets initialized ONLY ONCE. And each successive calls uses it as if it's a global variable. Its life-time is equal to the end of the program.
int f()
{
static int v = 0;
return ++v;
}
int main()
{
cout << f() << endl;
cout << f() << endl;
cout << f() << endl;
cout << f() << endl;
}
Output:
1
2
3
4
Online Demo : http://www.ideone.com/rvgB5
The justAbool is actually a regular static variable - it exists from the start of the program and is initialized only once. The special thing is that is is known only in this function - if you try and use it outside the function the compiler won't know what it is.
justAbool keeps its value after leaving the scope. What else did you want this code to do exactly?
function level static local variable, the initialization depends on variable types:
POD: initialized before main()
non-POD: initialized the first time, the line in the function is executed.

What's the difference between global variables and variables in main?

MyClass GlobalVar;
int main()
{
MyClass VarInMain;
}
A couple of things:
Typically, they're allocated in different places. Local variables are allocated on the stack, global variables are allocated elsewhere.
Local variables in main are only visible within main. On the other hand, a global variable may be accessed anywhere.
More differences:
If constructor/destructor of global object throws an exception, then function terminate is called and there is no chance to proceed. For local object, you can catch exception and do something (but it is still tricky to throw from destructor).
Order of construction/destruction of global objects is not well specified. This means, that generally for two global objects you cannot say, which one is constructed first. From the other hand, local objects are created at point of defintion and destructed at end of block in order reverse to order of creation.
Scope... (already mentioned)
In general, it is not a good practice to use global objects without very strong reasons to do so. Using of globals often leads to code which is hard to maintain.
The variable VarInMain is a local variable and can only be used inside the function where it is declared, in your case, the main function. The GlobalVar can be used in every function of your program because it was declared outside of a function. This is called Scope.
Scope. VarInMain can be accessed directly only by code in main. GlobalVar can be accessed directly by code in any function in the file.
A simple example:
int y = 43;
void foo() {
// y is visible here, x is not
}
int main() {
int x = 42;
foo(); // x is visible here, but not when we enter the foo() function
}
A global variable is visible globally, across all functions.
A local variable is visible in the scope in which it is declared only. if you declare a local variable inside main, it will be visible there, yes, but not in functions that are called from main.
VarInMain is accessible only within the main() function. If main() calls another function, that function will not have access to it. This is function scope.
GlobalVar is accessible in every function in the same file. If you put extern MyClass GlobalVar; in a header, then it can be used in any function in files which have or include that declaration. This is global scope.
Another difference: the order of global object initilization is undefined.
For example:
static Integer Global_Integer(5);
static Foo Global_Foo;
As these are objects, the C++ runtime will call their constructors when initializing them, but we can't predict the order in which this will happen.
Another difference:
Global variables will be initialized before the program starts (i.e. main() gets called) whereas the local variables are initialized as execution reaches that point (i.e. just after main is called in the above example).
globals can be used in functions declared outside of main, while anything declared in main, must be passed to another function first.
Another one: The global variables (or variables in any other namespaces) are initialized to (T)0, with T being the type of the variable (in case it's a simple non-class type), arrays and classes are initialized like that for all their elements.
But in my opinion, it's a good idea to explicitly initialize things anyway, and not rely on that zero initialization since it improves readability of the program when the initial value is explicitly mentioned. It's however still useful to know when reading someone else's code, always keeping in mind the compiler will initialize those automatically.
The local variable when it is not declared static isn't automatically initialized. So you have to do any initialization on your own in case T has no constructor doing it for you. Always keep that in mind.
A global variable is accessible to any function. A variable in main acts exactly like any other local variable, and is only accessible to code in main.
Also, if main (or another function) calls itself, the local variables will be copied, but global variables will not.
int x = 0;
void myfunction()
{
x++;
printf("%i ",x);
}
int main()
{
myfunction();
myfunction();
}
This example will output:
1
2
Moving the "int x = 0;" into myfunction will output:
1
1
Because the local variable gets initialised each time myfunction is called.
LOCAL VARIABLE
It is a variable which is declared within a function or within a block. It is accessible only within a function/block in which it is declared.
GLOBAL VARIABLE
It is a variable declared outside all the functions. It is accessible throughout the program.