G
G
Governor2017-05-30 22:16:58
OOP
Governor, 2017-05-30 22:16:58

C++. How is a local object returned by functions?

I read about the copy constructor. I figured out about passing arguments to a function, but I got confused with the return of a local object by a function.
There is a simple code:

#include <iostream>
using namespace std;

class samp {
public:
  int a; //Данные объекта

  samp()
  {cout << "Конструктор стработал!" << endl;}
  ~samp(){cout << "Деструктор стработал!" << endl;	}
};

samp func() //Функция возвращающая локальный объект
{
  samp ob;
  ob.a=255;
  return ob;
}

int main()
{
setlocale(0,"");
  int act;
  do{
    cin>>act;
    samp ob;
    ob = func();
    system("pause"); //Пауза на обдумывание
  }
  while(act);

system("pause");
return 0;
}

Here is the result:

The constructor worked!
The constructor worked!
The destructor worked!
The destructor worked!
Press any key to continue. . .
The destructor worked!

First, a local object is created in main, the constructor fired.
A function is called that creates its own object, the constructor has worked.
After assigning a value to a variable, a temporary object is created that stores this value, and the local object is deleted, the destructor fires!
Then, the variable in main gets that value, overwriting the previous one, and the temporary object is deleted, the destructor worked!
Pause...
At the end of the loop, the temporary object is destroyed, the destructor also fires.
It feels good.
But if you change the lines:
samp ob;
    ob = func();

on the
samp *ob;
    ob = &func();

The result becomes like this:

The constructor worked!
The destructor worked!
The destructor worked!
Press any key to continue. . .

The object is created only in the function, the constructor worked.
A temporary object is created and the local one is deleted, the destructor fired.
The pointer gets an address..
Stop.. And what address did it get, a temporary object?
The temporary object is destroyed, the destructor fires.
It turns out that the pointer received the address to the freed temporary object?
I tried to write data to this object ob->a = 100;
The OS didn't throw any errors.
Please help me figure it out, I'm confused :(

Answer the question

In order to leave comments, you need to log in

1 answer(s)
T
tomatho, 2017-05-30
@Mr-Governor

For local variables, the destructor is always called, so there are techniques for using this property for some needs, such as locking a mutex in a constructor, and unlocking in a destructor.
Ordinary pointers store an address. For ordinary pointers, the destructor does nothing.
But if a local variable is not a pointer, or a smart pointer, then there may be something in its destructor, thereby the object can free up memory, or perform some other manipulations.
Smart pointers allow for more flexible memory management. (shared_ptr, unique_ptr...)
From a technical point of view, they are no different from ordinary classes (structures).
They were simply written in advance for your convenience with appropriate implementations of constructors, destructors, and other operators.
After the memory is freed, the address does not cease to be an address, so all manipulations remain possible, except for reading and writing. This is already as lucky. Another thing is that it's not normal behavior to read/write freed memory. She may already be busy with something else, or changed.
Therefore: never return references or addresses of local variables, except for those that are in fact global: for example, those declared as static.
However, such a static variable is in a single instance, which means that it cannot be accessed simultaneously from several threads. More precisely, it is possible, but this is not normal, it will lead to errors.
Oh yeah, I forgot to answer the title.
I don’t know for sure, first I’ll describe how you can understand this, and then I’ll indicate what accuracy I don’t know.
It can be understood as follows: you declare a local variable in the calling function (caller), and then assign the result of the call to this variable. This variable is on the stack of the calling function (caller).
The function you call (callee) also has a local result variable.
And after the call is over, the caller assigns the result from the callee via the copy operator.
I.e
What is a constructor with a call parameter? Well, for example like this:

#include <string>
int meaning_of_life()
{
  return 42;
}

std::string wat()
{
  return "wat"; // тут будет вызван std::string("wat")
}

int main()
{
  int a(meaning_of_life()); // тоже самое, что и int a = meaning_of_life();
  std::string s(wat()); // тоже самое, что и std::string s = wat();
  return 0;
}

In this case, the result is used directly in the constructor, so the copy operator is not needed. In this case, the constructor is called a copy constructor.
About the accuracy. I do not know how the standard regulates where and how the result should be transmitted. And I also don’t know if there are optimizations that write from the callee directly to the caller.
On StackOverflow they write what optimization compilers have that pass the result by reference or pointer, whatever that means.
And finally: references are no different from pointers in technical terms. It's just syntactic sugar.
Correct me if I'm wrong anywhere. I will be glad.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question