Restrictions on local variable usage in C++? - c++

I had a few questions in a technical interview that I thought I knew, but wanted to double-check (they said I passed it, but I was unsure about these):
A variable declared inside a Class Method... Can that be used outside of that method, like for instance in another method? (I said no)
Can a variable declared inside a method be passed as a parameter to another method?
(I said yes but I wasn't sure)
This is for an entry-level C++ position and I'm used to C, so I wanted to double-check my understanding of C++/OO concepts.

A variable within a class method, that's instantiated within that method and wholly contained within that method, can only be used within that method. Its lifetime is finite. Edit: to clarify, I'm not saying it can't be passed to another function call within the function scope and I'm not talking about instantiating a member variable or static variable.
Yes, you can pass it to another method if that method is called from within the method it exists. Why? Because its lifetime it tied to the parent method, not the one that is called from within the method.
Let me illustrate:
//aVar does not exist.
int foo(){
int aVar = 1; //it's been born
cout << doSomething(aVar); // still alive
return aVar; //still alive but a copy is being returned from the function. Not aVar itself!
} // it's dead, man

Normally a variable's lifetime is inside the block it's declared in. So at the end of the scope it is destroyed.
BUT there's the case of Static Local Variable which is declared inside a method, but the value is saved in memory after the block is finished. Every call to that function will "see" the value of that variable. So, you could have a trick question, that the variable CAN be used in another instance of that method.
Yes you can pass it.

Contrary to popular belief, a variable declared in a member function can be used in another member function. There are two obvious routes to this.
The first is if that member function calls another member function, passing a pointer or reference to that variable to the second member function. The variable exists from the time the first member function is called until it exits from that call; if it calls some other function during that time, that other code can use the variable (if the member function does something to give it access).
The second is if you're dealing with a static variable defined in a member function. This is (for one example) the essence of the Meyers singleton. A static variable is defined in a member function, and not only other members of the singleton, but in fact all the rest of the program that accesses the singleton object use the static variable defined in that member function.
For the second question, you're right -- a variable defined in a member function is pretty much like any other local variable. It can be passed as a parameter, just like anything else.

First Question: Yes, you are correct. Variables declared within the scope of a class method are only valid in that scope. When the method exits, that variable loses scope and is no longer usable.
Second Question: Yes, the method can call another method, using that locally scoped variable. The variable remains in scope and is usable through the duration of the second function call.

First of all.....a variable declared
inside a Class Method....can that be
used outside of that method, like for
instance in another method
In C++, no.
Secondly, can a variable declared
inside a method be passed as a
parameter for another method?
In C++, in a non-concurrent application, yes. In the case of concurrency and the receiving function takes its parameter by reference you must make sure the object you pass doesn't destruct while the receiving function uses it.

First of all.....a variable declared inside a Class Method....
can that be used outside of that method,
like for instance in another method
Sure. For example,
class Base {
public:
static Base *create_instance() {
static int variable_declared_inside_class_method = 0;
return new Base(variable_declared_inside_class_method);
}
Base(int &var_) : var(var_) {}
int inc_var() {
var++; // this method uses variable_declared_inside_class_method
}
private:
int &var;
};
Note that variable_declared_inside_class_method does not live on the stack. This is why it works here.
Secondly, can a variable declared inside a method be passed as a parameter
for another method?
Absolutely.

Related

memory layout of C++ object

As far as my understanding all the member functions will be created in separate memory when class definition and is common for all objects. And only the member variables are created individually for each object. But how member function is executed when called using object?
Where is the address for these member function will be stored?
class B{
public:
int a;
void fun(){
}
};
int main(){
B b;
std::cout<<sizeof(b)<<std::endl;
}
If I execute this program, I get the output as 4(which is for only member variable). But calling b.fun() calls its member function correctly. How it is calling without storing its address within the object? Where the member function address are stored?
Is there anything like class memory layout where these addresses will be stored?
Non-virtual member functions are extremely like regular non-member functions, with the only difference between them being a pointer to the class instance passed as a very first argument upon invocation.
This is done automatically by compiler, so (in pseudo-code) your call b.fun() can be compiled into
B::Fun(&b);
Where B::Fun can be seen as a usual function. The address of this function does not have to stored in actual object (all objects of this class will use the same function), and thus size of the class does not include it.
Is there anything like class memory layout where these addresses will be stored?
There is for functions declared virtual, yes. In this case, the addresses of said functions are stored in a table and looked up at runtime. This in turn allows your code to dispatch to the correct function depending on the object's type when the function is called.
Non-virtual functions do not work this way. They're stored in the same way as free (i.e. non-member) functions, with the function name prefixed by the name of the class. No storage space within the object itself is required.
In both cases, a hidden this pointer is passed to the called function. This is what 'connects' it to your object.

Is it correct that if a global function uses non-local variables, then it's a closure?

I've been quite confused about what a closure is in C++. I've read this What is a 'Closure'? but nearly all answers are referring to JavaScript but I think there are some differences about closure between C++ and JavaScript. So I found it difficult to match the JavaScript description of closure to C++.
For example, nearly all answers are taking a function returning a function as an example to demostrate closure in JavaScript. But I don't find the similar pattern in C++.
What's more, in JavaScript there is no such thing called "capture list".
I was told that if a function uses non-local variables (from outer scope or global scope), then it's a closure. Is it correct?
Example 1:
int a = 3;
int am_I_a_closure(int c){
return c + a;
}
int main(){
}
Why capture list is required? Can't lambda in C++ just work like JavaScript nested functions?
Or in another way of speaking, can't lambda in C++ just work like the same way as global function accessing global(non-local) variables?
I mean, through normal name look-up proccess, if a name is not found in the current scope, then find it in the outer scoper, then more outer scoper...
Why capture list is needed? Why need to capture outer scope variables? Can't that be done through normal name look-up?
Example 2:
int main(){
int a = 3;
{
int b = 5;
{
int c = 4;
{
std::cout << a+b+c <<std::endl;
}
}
}
}
Example 3:
int main(){
std::vector<int> values = {1,5,3,4,3};
int a = 3;
std::find_if(values.begin(), values.end(), [](int value) {return value > a; }); //Error, `a` is not captured.
}
Again, in Example 3, why a is need to be captured instead of normal name look-up as in Example 1 and Example 2?
It's important to understand that "closure" is a concept that has a very specific meaning in functional programming. C++ however is not a functional language; it doesn't care all that much about strict adherence to functional programming terminology. It simply defines various functionality, some of which may or may not map well onto that terminology.
JavaScript and C++ are different languages. In JavaScript, a function has a property called being a "first-class object". This means that, when you execute the code to create a "function", you are creating an object that represents that function.A variable containing a function is fundamentally no different from a variable containing a string or a variable containing an array or whatever else. You can overwrite a variable that contains a function with an array, or vice-versa.
In particular, functions as first-class objects can have state associated with them at the point of their creation. If such a function reaches out of its scope to access a local variable, then that scope can be stored as part of the function's state; this state will be accessed automatically when you attempt to use that variable in the function. So it appears that you're reaching "out" of the function's scope, but you're not; the scope was brought "in" with you, and you're just accessing that.
In C++, a function is not a first-class object. You can get a pointer to a function, but function pointers are explicitly distinct from object pointers (casting between the two is not even required to be valid). A function is not "created" or "destroyed" as far as the C++ language is concerned; every function is always there, from the start of the program to its end.
C++ functions can access global variables, but that's because they're global. The location of a global variable is baked into the executable at compile/link time, so no special state needs to be stored with the function in order to access it.
However, C++ does have a useful concept that can help to create the effect of a first-class function object. Namely, a class type can overload the function call operator operator(). This allows an instance of a class to be called as if it were a function. Class instances are objects and can have internal state (aka: member variables), and the operator() overload is just a member function of the type.
Given all of that, you can create something that simulates a properly scoped function object. All you need is a class that has member variables that correspond to the variables outside of the function's scope which it references. These members can be initialized in the class's constructor by passing the external values to the constructor. Then you have a valid object which you can call, and it can access those "external" variables by using its member variables.
This is all a C++ lambda is. It wraps all of this up in "nice, neat" syntax. It writes a class for you; it writes the member variables you "capture" from the external world for you, and it calls the constructor and passes those variables for you.
However, C++ is a language that tries hard not to make something more expensive than you need it to be. The more external variables you use, the more internal member variables the lambda will need, and thus the bigger the class will be and the longer it will take to initialize/copy/etc. Therefore, if you want to use some external variable (which is implemented as a member variable), C++ requires you to either explicitly list it (so that you know that you meant to capture it) or to use the default capture mechanisms [=] or [&] (so that you are explicitly giving up your right to complain about accidentally making your lambda type huge and/or slow).
Furthermore, in JavaScript, everything is a reference. Variables store references to arrays, functions, dictionaries, etc. JavaScript is a reference-based language.
C++ is a value-oriented language. A variable in JavaScript references an object; a variable in C++ is an object. You cannot replace one object with another in C++; you may copy over the value of an object, but it is still that object.
As such, how a lambda ought to capture a particular variable becomes relevant. You can capture variables by value (copying the value into the hidden member) or by reference (referencing the object).
This is of particular importance because C++ is not garbage collected. That means that, just because you have a reference to an object does not mean the object still exists. If you have a variable on the stack, and you get a reference to it, and that reference exists past the point where the stack variable goes out of scope... that reference is now useless. In JavaScript, it'd be fine because of garbage collecting. But C++ doesn't do that. You have a reference to a destroyed object, which cannot be used.
So if you want a lambda to capture local variables and you want the lambda to persist past the point where the variables no longer exist, you will need to capture such variables by value, not by reference.
Capturing by value or by reference is determined by how you list the variable in the list of captures. &x means to capture by reference, while x is a capture by value. The default capture [=] means to capture by value by default, with [&] meaning reference capture by default.

does c++ create an instance when declare a static member?

does c++ create an instance when declare a static member?
I think this is a concept question, maybe. I am not so sure.
I mean when I declare a class with a static member inside, would there be a real space for the static member? As I knew, a static member could only exit uniquely once in a class. Is the static space and function there after I declared it? If so, does it mean I can call a function (static?) without defining a real object?
Thanks
Yes, if you declare a static member, real space for it exists. It's basically like a global variable in that sense, except for the limited scope within which it's accessible.
Yes, you can call a static function without making an instance.
Actually instance of class is never created automatically.but even before creating an instance you can call that variable...static members are seperately treated common to all instances of a class.

The fourth parameter in pthread_create function

Code like this:
int code = pthread_create(&d->thread_id, &attr, QThreadPrivate::start, this);
which QThreadPrivate::start is a static function.
So,what use is the fourth parameter this? And what is the difference if this is replaced by NULL?
This is a common idiom. You want to start a thread, but you want that thread to operate on a specific object. So you need to pass the thread a pointer to the object you want it to operate on. If you're within a member function for that object, the this pointer points to the object you're operating on. You can't pass a pointer to a member function directly (because the type would be different), so you use a static member function whose sole purpose is to cast the this pointer back to the correct type and run a non-static member function.
If you changed this to NULL, the thread would have no idea what object it was supposed to operate on. Likely, QThreadPrivate::start would fault or fail, since it would be unable to invoke a non-static member function on the instance without a pointer to that instance.
Say you have a class that has a normal member function that takes no parameters and returns no parameters. You have some code that has no idea about your class or any of its structures. You want to give that code enough information to call that member function on a particular class instance. What do you pass it? You can't pass it a pointer to the member function because with no idea about your class, it can't call a normal class member function. Answer: You pass it a pointer to a static member function whose implementation calls the normal member function, and you pass it a pointer to the instance whose method you want it to invoke.
The fourth parameter of pthread_create is passed untouched to the thread function and allows that function to change behaviour based on that argument.
OpenGroup documentation for pthread_create, detailing this, can be found here.
In this case, it's simply passing the pointer to the current object, presumably so that the start function can use that to access member variables for the specific object.
If you pass NULL instead, the created thread will get NULL and won't be able to access object specific data (without crashing and burning badly with a null pointer dereference).
You may think that, because QThreadPrivate::start is a static function, it wouldn't be able to access non-static members any way (since it generally doesn't have an object to work on).
But that only applies to implicit access - there's nothing stopping you from accessing object data through an explicit this pointer, providing you follow the access rules (e.g., no access to private data).
The fourth parameter is passed to the thread when it starts. QThreadPrivate::start can use it (after an appropriate cast) to call an object specific member function.

Will a variable go out of scope when the function returns?

void main()
{
File f;
DoSomething(f);
DoSomething2(&f);
}
void DoSomething(File& f)
{
f.Process();
} // will f go out of scope when this function returns?
void DoSomething2(File* f);
Two questions:
As seen in the comment, will f go out of scope when the function returns?
Do you suggest writing function using reference or pointer? (I'm talking about private functions)
f the reference local to DoSomething will go out of scope, but this obviously has no consequences.
The f object local to main goes out of scope only after the end of the main (which, incidentally, should be int main.
To sum it up, references are aliases to objects, but the original objects retain their scope, as happens with pointers.
A common suggestion is use references when you can, pointers when you have to.
In general I use references whenever I need a parameter to be passed - duh - for reference, and pointers e.g. when I want that parameter to be optional1 (pointers can be NULL), when I'm accepting arrays, ... and in general, I'd say, when in the function I'm going to use the pointer as a pointer, not dereferencing it all the time.
although overloads and default values can be better than a NULLable parameter in many situations.
f will not fall out of scope because it is an argument to the function, i.e., it was not created inside of the function.
It is preferable to take a reference if possible as it is guaranteed to be a valid reference and not null (yes, it can be null if you use some trickery and invoke undefined behavior, but then your program isn't valid anyway).
Scope is a compile-time concept, not a run-time concept. It refers to the visibility of names, not the lifetime of objects.
You have three things named f. One of them is local to main; the others are local to DoSomething and DoSomething2, respectively. For the first two, the scope (of the name, not of the object) extends to the closing }.
The lifetime of the object named f that's defined in main extends until main returns. That's the only File object in the code you've shown us.
(And unless you're using a freestanding (i.e., embedded) implementation, it's int main(), not void main(). Complain to whomever or whatever taught you that void main() is correct.)
Of course not, f's scope is the function main. It will get destroyed when main returns (ie when your program exits).
As to your second question, references are always better (insert grain of salt here), you are guaranteed you're never going to get a null and the syntax is cleaner (opinion, I know).
When you call your "DoSomething" function, the do something function takes a reference of the f that's called from main. This means that the scope of the f in main is defined from the beginning to the end of main. The "f.process", by nature, does not go out of scope. It stays in the scope defined in main.
Question 1:
you are passing the address of a file and giving it the name f (whose scope is only the function DoSomething(&f). Calling a member function of the File object will never affect the scope of the f variable.
Sort Answer = no.
Question 2:
references from my understanding is a Java concept, passing by "reference" in C++ is done by sending an object pointer as an argument. Whether or not passing by a pointer is the best solution largely depends on the context of what you are doing.
Sort Answer = maybe?