0
#include <string>
#include <iostream>



class Type {
public:
    int x;
    Type(int a)
    {
        x = a;
    }

    Type(const Type& type1)
    {
        std::cout << "copy" << std::endl;
    }
};

Type Func() 
{
    Type s(1);
    std::cout << &s << std::endl;
    return s;
}

int main()
{
    Type c = Func();
    std::cout << &c << std::endl;
    std::cout << c.x << std::endl;
    system("pause");
}

C++ allocate memory for object in heap or stack? In Func, suppose "s" is allocated in stack, then why it don't be deconstructed? Why can i stiil call it in main(). I am very confused.

Tumb1eweed
  • 85
  • 6
  • 2
    Fun fact: C++ was designed so that you don'r need heaps or stacks. It's better if you phrase this question in terms of Dynamic and Automatic allocation. These will be the terms used in your C++ programming text if it was written correctly. – user4581301 Aug 31 '20 at 04:15
  • Add a destructor to `Type` and place a diagnostic output in it so that you can see when it is called. Example:https://ideone.com/n8teQN – user4581301 Aug 31 '20 at 04:16
  • The &s in the function is deconstructed and a copy is returned which is used in main(). As mentioned above, define a desctructor to observe this. – Sam Aug 31 '20 at 04:19
  • 1
    Where you are likely to get confused here is [a compiler will do anything it can to your code to make it run faster](https://en.cppreference.com/w/cpp/language/as_if), this includes discarding unnecessary copying. The [Copy Elision](https://en.cppreference.com/w/cpp/language/copy_elision) rules in a modern C++ compiler even allow elimination of calls to the copy constructor even if there are visible side effects like a print statement. For example, it could silently take `c` and pass it into `func` by reference and use it as `s`, eliminating the need to construct `s` and copy it back into `c` – user4581301 Aug 31 '20 at 04:21
  • The program should print the same two addresses – M.M Aug 31 '20 at 04:48
  • 1
    although it causes undefined behaviour by outputting uninitialized variable (the copy-constructor does not initialize `x`) – M.M Aug 31 '20 at 04:49
  • With GCC and C++11/14, you can try to compile with `-fno-elide-constructors` to see the difference: https://godbolt.org/z/Kvh5P9. – Daniel Langr Aug 31 '20 at 05:45
  • 's' is destroyed inside Func() but it isn't destroyed because a copy of it is passed to main() – Yashovardhan Singh Aug 31 '20 at 07:42

1 Answers1

3

By default, objects are are stored in the stack (unless their implementation has a dynamic allocator, e.g. a map). If you have your own class and instanciate it, it will live in the stack. However, this is not recommended since the stack ougth to be considered a precious and scarce resource. If you were to have a heavy object, or many light objects, it is better to allocate them dynamically.

In modern C++ versions, we have what is called move semantics and move constructors (which can be automatically generated by the compiler). Basically, the compiler optimizes your code. In this case, it would be inefficient to copy the object s to c when s is going to be destroyed anyway. What the move constructor does is basically steal the data from s and give it directly to c (in this case, just using c as an alias for the memory location in which s is stored).

emegona
  • 168
  • 1
  • 12
  • No worries. Note this isn't necessarily move semantics either. As soon as you declare a copy constructor, [the default move constructor is disabled](https://en.cppreference.com/w/cpp/language/move_constructor#Implicitly-declared_move_constructor), so the asker's example must be eliding. – user4581301 Aug 31 '20 at 04:43
  • Thank you for your comment. You are right, I totally forgot move constructors are disabled when a copy constructor is declared. – emegona Aug 31 '20 at 04:49
  • No 'by default' about it. An object declared as a local variable is allocated automatically; an object iniitalized via `new` is allocated dynamically. – user207421 Aug 31 '20 at 05:43
  • wait, so Type c = Func() calls move constructors, not copy constructors? How can i tell this two constructors? when to call move and when to call copy? – Tumb1eweed Aug 31 '20 at 06:40
  • In this case no, it doesn't. As user4581301 said, move constructors are disabled when copy constructors are declared. In this case, we might be seen [copy elision](https://en.cppreference.com/w/cpp/language/copy_elision). I think [this video](https://youtu.be/fSB57PiXpRw) illustratres this process very well. – emegona Aug 31 '20 at 06:53