Is 'this' a local variable? - c++

Here I am taking an example of overloading the increment operator:
class Digit
{
int m_digit;
public:
Digit (int value) //constructor
{
m_digit = value;
}
Digit& operator++();
int ret_dig (){return m_digit;}
};
Digit& Digit::operator++()
{
if (m_digit == 9)
m_digit = 0;
else ++m_digit;
return *this;
}
int main ()
{
Digit my_dig (5);
++my_dig;
return 0;
}
I have been told that local variables can't be returned. Isn't "this" a local variable? Here is what I think:
A pointer of type Digit is attached to the member function (overloaded operator function). When compiler sees the line ++my_dig, that is an instance of Digit class, it calls the member function. The address of the instance my_dig is passed as argument to the function and there is a hidden "const Digit*" named "this" to catch the argument. "this" is dereferenced(implicitly) to access m_digit, that is a member variable of class Digit. All the increment or wrapping is done inside the function and a reference to dereferenced "this" is then returned to the caller. Yes, this is the point to my confusion. If "this" is a local variable of type const Digit*, shouldn't it contain garbage when returned because "this" is going out of scope where the block ends haaa?

this is an implicit parameter to all member functions which points to the object itself -- which has a strictly longer lifetime than the method. The parameter itself is a local variable, but the object that it points to exists outside the method.
In this case the object is created on the first line of your main function and then lives until the main method exits. Thus the object is safely alive throughout the call to operator++!

The *this is the object and not a local variable. Any temporary objects which the compiler deems necessary to allocate, such as those needed to complete a expression, has a lifetime to the end of the expression.
This becomes interesting for objects which has a destrctor, as the destructor run not when the individual parts of the expression is completed, but when the entire expression completes -- hence your *this variable will survive just sufficiently long to complete what is needed.
Have a look at this question for deeper discussion

this is a local variable, but it is initialized by &my_dig when it enters the method. The value of &my_dig has the same lifetime as my_dig, which ends at the end of the main block. So while this goes out of scope, the value of this is still valid.

Related

what is the scope of this variable in c++?

If i define a function like this
std::string& returnstring(std::istringstream &ist)
{
std::string temp;
std::getline(ist,temp);
return temp;
}
and if i use this temp which is passed by reference to another function like this
void displaystring(std::string &temp)
{
std::cout<<temp;
}
would the string temp still be in scope when i pass it by reference to displaystring function?
The scope of a variable is the scope where it is declared. std::string temp; is declared within the body of the function returnstring, therefore that function body is the scope of the variable. It is an automatic variable, and therefore its lifetime ends at the end of its scope and it is automatically destroyed.
The returned reference will be invalid (i.e. it is a dangling reference). If you attempt to access the non-existing object through the invalid reference, then the behaviour of the program will be undefined.
To fix the function, a simple solution is to return a value instead.
Nope since the temp variable is local to the returnstring function and once the code is out of the retuernstring function the temp variable is no longer valid.
If at all you want to send the reference and get the answer then better option is to send the argument by reference as below,
void copyLineAsString(std::istringstream &ist, std::string& tempString)
{
std::getline(ist,tempString);
return;
}
I have few other suggestions to your code for the good coding practice,
Never use the '&' for the return type / return a variable by reference. Use camel casing or _ separator for the function names(Ex returnString or return_string).
No. The scope of temp is limited to the block where it is declared. Because you declared it on stack (you didn't use the keyword new), the variable temp will be destroyed the moment you exit the function.
The only way to keep the variable would be to have the value of temp be copied to a variable outside the function. For example, this would work:
std::string returnstring(std::istringstream &ist)
{
std::string temp;
std::getline(ist,temp);
return temp;
}
Because the return value is a copy rather than a reference, you could then do
std::string returned_string = returnstring(ist);
And have the value of temp be copied into a newly declared variable that could be used for your displaystring function.
In general, I would avoid declaring variables inside a function that you will need outside the scope of the function. Instead, return by value whenever you are returning variables built inside of the function (not recommended for large arrays and objects, however).
this is the reference variable which refers to the current class object which has called it. it has scope only inside the class and the same as the lifetime of the object which called it.

if I return a class in my function, where does it store?

look at my code:
#include <iostream>
using namespace std;
class MyClass{
public:
char ch[50] = "abcd1234";
};
MyClass myFunction(){
MyClass myClass;
return myClass;
}
int main()
{
cout<<myFunction().ch;
return 0;
}
i can't understand where my return value is stored? is it stored in stack? in heap? and does it remain in memory until my program finished?
if it be stored in stack can i be sure that my class values never change?
please explain the mechanism of these return. and if returning structure is different to returning class?
MyClass myClass; is stored on the stack. It's destroyed immediately after myFunction() exits.
When you return it, a copy is made on the stack. This copy exists until the end of the enclosing expression: cout << myFunction().ch;
Note that if your compiler is smart enough, the second object shouldn't be created at all. Rather, the first object will live until the end of the enclosing expression. This is called NRVO, named return value optimization.
Also note that the standard doesn't define "stack". But any common implementation will use a stack in this case.
if returning structure is different to returning class?
There are no structures in C++; keyword struct creates classes. The only difference between class and struct is the default member access, so the answer is "no".
It's up to the implementation to find a sensible place to store that value. While it's usually on the stack, the language definition does not impose any requirements on where it's actually stored. The returned value is a temporary object, and it gets destroyed at the end of the full statement where it is created; that is, it gets destroyed at the ; at the end of the line that calls myFunction().
When you create an object in any function it's destroyed as soon as the function execution is finished just like in variables.
But when you return a object from a function firstly compiler creates a local instance of this object in heap called unnamed_temporary then destroyes the object you created. And copies the contents of unnamed_temporary on call. Then it destroyes this unnamed _temporary also.
Anything you create without the keyword new will be created in stack.
Yes,contets of your variable ch will not change unless you access that variable and change it yourself.
The instance returned by myFunction is temporary, it disappears when it stop to be useful, so it doesn't exist after after the cout <<.... Just add a destructor and you will see when it is called.
What do you mean about can i be sure that my class values never change? ? You get a copy of the instance.
returning structure is different to returning class? : a struct is like a class where all is public by default, this is the alone difference.
Your function is returning a copy of an object. It will be stored in the stack in memory.
The returning obj. will exist until the scope of that function. After that, it will be destroyed. Then, your expression cout<<function(); will also have the copy of that obj. which is returned by the function. IT will be completely destroyed after the running of this cout<<function(); expression.

Passing a const reference as a function parameter in a class member function

Suppose we have a class called Line that contains the following modifier that assigns a value to a class data member.
void Start(const Point &start);
The line class contains two data members called start and end which are both Point objects. Since the start variable in the function parameter is a reference, and I implement it as follows:
void Line::Start(const Point &start) {
m_start = start;
}
In the main function I have the following.
Line line;
Point start(1, 1);
line.Start(start);
Would the m_start data member now refer directly to the start Point object in the main function since it was passed by reference?
Would the m_start data member now refer directly to the start Point
object in the main function since it was passed by reference?
No. One of the properties of C++ references (and one of the ways in which their behavior differs from that of pointers) is that it's impossible to reseat a reference -- that is, you can't make a reference that was 'referring to' one thing later 'refer to' a different thing. (And of course if your m_start member variable was of type Point rather than type Point &, then there's no reference to attempt-to-reseat anyway)
Instead, start's copy-constructor will be invoked to copy start's contents into your m_start member-variable.
The upshot is that your Start() method will behave exactly like a similarly-implemented void Line::Start(Point start) method would, with the following exceptions:
In your const Point & version of Start(), no separate/method-local copy of the Point object is made
In your const Point & version of Start(), trying to modify start from within the method would be a compile-time error (whereas in the pass-by-value version, the code inside Start() could modify the argument, but the modifications would never be visible outside of the Start() function since they'd only modify the local variable/parameter)

Return object with 2 optional ctors in function

I have function in c++ with 2 optional c'tor of an object I've built (one with something in vector "vals" and other without).
...
RecievedMessage a(sc, type);
if (!vals.empty()){
//a.~RecievedMessage();
RecievedMessage a(sc, type, vals);
}
return &a;
}
the line in // is optional.
Would it work (with or without the optional line)? Why? If no, how to fix it without setter for "vals"?
thanks a lot.
No, it wouldn't work.
RecievedMessage a(sc, type);
// Here we construct 'a'
if (!vals.empty()){
//a.~RecievedMessage();
// If we enable this line, we destroy 'a'
RecievedMessage a(sc, type, vals);
// Here we construct a second 'a' that only exists in this block
}
// End of block: The inner 'a' is destroyed here automatically
return &a;
}
// End of block: The outer 'a' is destroyed here, again.
Destroying an object twice has undefined behavior. You don't want that.
If you don't call the destructor manually, the outer a is only destroyed once, which is good.
But in either case, RecievedMessage a(sc, type, vals); has nothing to do with the outer a and merely creates another variable.
There would be ways to work around that, but the final line of your code makes it all pointless:
return &a;
You're returning the address of a local variable. This is broken in and of itself: When the function returns, all of its local variables are destroyed automatically, so what you're returning is an invalid pointer.
Your code is all over the place, but what I think you're looking for is something like this:
ReceivedMessage *MakeReceivedMessage (foo sc, bar type, vector<whatever>& vals)
{
if (vals.empty())
return new ReceivedMessage (sc, type);
return new ReceivedMessage (sc, type, vals);
}
Of course, it would be better in this example to just have a single constructor and have the object test whether vals is empty when appropriate, but, in general, you can call whatever constructor you like whenever you like. Just manage your object lifetimes properly (and don't - ever - return a pointer to an object on the stack).
Example usage (to manage the lifetime of the object returned properly):
std::unique_ptr<ReceivedMessage> MyReceivedMessage (MakeReceivedMessage (...));
MyReceivedMessage->DoFunkyStuffWithMessage ();
....
Or, as melpomene points out, you can return a std::unique_ptr<ReceivedMessage> in the first place. Some (many?) would prefer that. You can construct it with std::make_unique.
There are three main issues with your code right now:
First of all, your commented out call to the destructor ~ReceivedMessage() should not be there at all. In C++, the destructor of objects is automatically called when an object's lifetime ends (either when it goes out of scope, or when delete is called if it was dynamically allocated with new). While there are some situations where explicitly calling a destructor is necessary ("placement new" for example), these are situations you're very unlikely to come across.
Secondly, your RecievedMessage a(sc, type, vals); declaration in the inner if does not replace the value of a in the outer scope. This just creates another variable of the same name which shadows the outer a, while return &a; in the outer scope can only refer to the outer a. The inner a no longer exists at this point as it has gone out of scope.
A way to fix this issue is to instead assign a new value to a by using the = operator and constructing a temporary ReceivedMessage:
if (!vals.empty()) {
a = ReceivedMessage(sc, type, vals);
}
This should work as long as a correct operator= is defined (implicitly or otherwise) for ReceivedMessage.
Thirdly, your function is returning a pointer to the local variable a. Since objects in C++ are destroyed as soon as they go out of scope, a no longer exists by the time the function has returned, so the ReceivedMessage * pointer the calling code obtains is invalid and it would be undefined behaviour to dereference that pointer and make use of it.
There are a couple of fixes to this issue:
The first option is instead of returning a pointer (ReceivedMessage *), just return a ReceivedMessage by value.
ReceivedMessage foo()
{
ReceivedMessage a(123);
return a;
}
This should work as long as a correct copy or move constructor is defined (implicitly or otherwise) for ReceivedMessage.
The second option is to make use of std::unique_ptr, and make your function instead return std::unique_ptr<ReceivedMessage>.
#include <memory>
std::unique_ptr<ReceivedMessage> foo()
{
std::unique_ptr<ReceivedMessage> a;
if (vals.empty()) {
a = std::make_unique<ReceivedMessage>(sc, type);
} else {
a = std::make_unique<ReceivedMessage>(sc, type, vals);
}
return a;
}
The advantage to this approach is that unique_ptr is nullable, so you can create a null unique_ptr without having to construct a ReceivedMessage straight away. Additionally, you can move and assign unique_ptr values safely without having a correct operator= or a correct copy / move constructor defined.
The calling code may look like this, when using unique_ptr:
std::unique_ptr<ReceivedMessage> message = foo();
foo->bar();
as opposed to the following when using ReceivedMessage directly:
ReceivedMessage message = foo();
foo.bar();

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.