0

Let's take the following class for example

class Shape{
    public:
      Circle (int x): number(x){}
      virtual area () {return x**2;}

    private:
      int number;
}

In main we create the objects

int main(){
    Shape *foo = new Shape(8);
    Shape *bar = new Shape(65);
    Shape &obj1 = *foo, &obj2 = *bar;
}

I believe the objects 1 and 2 are stored in the heap. Why is that? As a side question. Does the keyword virtual, or/and the way objects are defined (eg. obj1 = *foo), impact the positioning thereof in the memory?

  • 9
    `foo` and `bar` have dynamic storage duration, and are stored in the *freestore*. The C++ Language Specification doesn't mention *"heap"* as a storage. `obj1` and `obj2` are **references**. They are aliases to existing objects, and exist during compile-time only (like all variables). They (usually) are not reflected in the executable image, or memory at run time. – IInspectable Jul 21 '16 at 20:22
  • Reference: http://stackoverflow.com/questions/10157122/object-creation-on-the-stack-heap – Omid CompSCI Jul 21 '16 at 20:23

1 Answers1

1

There are (broadly) two types of objects W.R.T. their memory management:

  1. An object can be fully constructed during compile time
  2. An object can only be fully constructed using some information that is not available until after the program is run

For example, any constexpr type object can be fully evaluated and constructed during compilation and as such can be placed into a memory data segment as an optimization (from a purist point of view it is a valid, yet far from optimal, to construct such objects during run-time. But this will waste CPU cycles and make the initialization/startup longer).

Here are a few examples of such objects:

const char * const helloWorld = "Hello, world!";
struct TSilly{
    TSilly(int _i = 0) : i(_i) {}
    int i;
};
const TSilly silly1;
const TSilly silly2(42);
TSilly silly3;   // doesn't have to be constexpr to qualify for static allocation.
                 // This one you can declare as /*extern TSilly silly3;*/ in
                 // header file and access from other compilation units
static TSilly silly4;  // can be local to compilation unit, too

int main()
{
    return 0;
}

All the other objects would have to wait until the run-time to be constructed.

Examples of such objects:

const char * exeName1; // statically allocated by compiler

int main(int argc, char **argv)
{
    exeName1 = argv[0];  // now points to a string

    // buffer is allocated in free storage (heap) bu variable itself is on stack
    char * exeName2 = new char[strlen(argv[0] + 1];
    strcpy(exeName2, argv[0]); // now contains a COPY of a string

    char exeName3[1024];  // likely allocated on stack, be careful with that as stack space is limited
    strncpy(exeName3, argv[0], 1024); // will COPY at most 1023 characters from a string

    delete [] exeName2;  // don't forget to clean up
    // exename3 will be auto-cleaned when we exit the function

    return 0;
}

As you can see an object in C++ will be put into a data segment or into free storage (heap) depending on its lifetime.

Only the dynamically allocated objects are guaranteed to be put into free storage. I don't think the spec makes any promise of usage of data segments for statically allocated objects - it is up to the compiler to perform and utilize that optimization.

For more info google "C++ storage classes".

There are plenty of advanced memory management topics you might want to look into. The most relevant one to this discussion is probably the in-place constructor which allows you to have a run-time object constructed in a memory allocated in executable's data segment.

recnac
  • 3,744
  • 6
  • 24
  • 46
YePhIcK
  • 5,816
  • 2
  • 27
  • 52