Reputation: 279
So I have 2 classes for this example:
E
, which prints a message when it is destroyed + can store integer value
T
, which stores instance of E
and can return it through a method
Code:
class E
{
public:
E();
~E();
int test;
};
E::E(){}
E::~E()
{
std::cout << "E is destroyed" << std::endl;
}
///////////////////////////////////////////
class T
{
public:
T();
~T();
E data;
E get();
};
T::T(){}
T::~T(){}
E T::get()
{
return this->data;
}
///////////////////////////////////////////
int main()
{
E e;
e.test = 2;
T t;
t.data = e;
E* e2;
{
e2 = &(t.get());
std::cout << "end of block" << std::endl;
}
std::cout << e2->test;
}
Result of running my code is:
E is destroyed
end of block
which means that some instance of E
is destroyed before reaching the end of {}
Questions:
1. I experimented a bit. Is it correct that t.get()
value in e2 = &(t.get());
line is destroyed immediately because it was not assigned by value to any variable?
2. If this value is destroyed, that means that e2
pointer is invalid. But std::cout << e2->test;
line still prints saved integer value. Is pointer still valid somehow or this data just occassionally stayed at this place of memory?
Upvotes: 3
Views: 188
Reputation: 394
By default, memory that is freed is not set to a specific value. Thus, it keeps the last value it had. What is happening is that the address of your copy of t->data is stored in e2. Then, the compiler frees said copy because you are not using it anymore. Thus you have a call to the destructor.
However, you are indeed keeping the values in memory so your pointer can still access them. (But i am guessing that with valgrind that is spitting out an invalid read.)
So yes, your pointer is indeed invalid, however it still can access the data.
Rephrased to answer logically your questions :
1) It's a copy and not assigned so destroyed immediately.
2) The values exist at the address however the address is considered invalid and can lead to memory issues (Segmentation fault for example)
Upvotes: 1
Reputation: 11961
The original code won't compile by GCC because the function
E T::get()
{
return this->data;
}
returns value. When you assign the pointer e2 = &(t.get());
in the block, it makes a temporary copy of data
. After you exit from the block, when you reference the pointer e2
, it no longer points to the actual variable because the temporary variable is out of scope. So in order to correct this, you can modify the code to return a reference to data
field of class T
:
E& T::get()
{
return data;
}
After that when you run the code again, you will see:
end of block
2
E is destroyed
E is destroyed
Note that the two E is destroyed
is due to the fact that there are two E
instances, one for e
, and the other for t.data
because the code t.data = e;
will invoke the copy constructor of class E
. Therefore finally there are two E
objects get destructed when the program exits.
Upvotes: 2