What happens to the return value?

So I have 2 classes for this example:
E

that prints a message when it is destroyed + can store an integer value
T

, which stores an instance E

and can return it using the 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;
}

      

The result of running my code:

E is destroyed
end of block

      

which means that some instance is E

destroyed before reaching the end{}

Questions:
1. I experimented a little. Is it correct that the value t.get()

in the string is e2 = &(t.get());

destroyed immediately because it was not assigned by value to any variable?
2. If this value is destroyed, it means that the pointer is e2

invalid. But the string std::cout << e2->test;

still prints the stored integer value. Is the pointer still valid in some way, or is this data just stuck in this memory location from time to time?

+3


source to share


2 answers


The source code will not compile with GCC because the function

E T::get()
{
    return this->data;
}

      

returns a value. When you assign a pointer e2 = &(t.get());

to a block, it creates a temporary copy data

. After exiting the block, when you reference the pointer e2

, it no longer points to a valid variable, as the temporary variable is out of scope. Therefore, to fix this, you can change the code to return a link in the data

class field 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

have to do with the fact that there are two instances E

, one for E

and the other for t.data

, because the code t.data = e;

will call the copy constructor of the class E

. Therefore, finally, there are two objects E

that are destroyed when the program exits.

+2


source


By default, freed memory is not configured to a specific value. In this way, it retains the last value it had. It happens that the address of your copy of the data t-> is stored in e2. The compiler then frees the specified copy because you are no longer using it. This way you are calling the destructor.

However, you do store the values ​​in memory so that your pointer can access them. (But I'm guessing that's with valgrind, which spits out invalid reads.)

So your pointer is indeed invalid, however it can still access the data.



Rephrased to logically answer your questions:

1) This is a copy and is not assigned so destroyed immediately.

2) Values ​​exist at the address, however the address is considered invalid and can lead to memory problems (e.g. segmentation fault)

+1


source







All Articles