简体   繁体   中英

C++: Static pointers, static objects and dynamic memory allocation

Consider the below code segment:

#include <iostream>
using namespace std;

class p
{
    public:
    int* q;
    p()
    {
        q = new int(100);
    }
    ~p(){
        delete q;
    }
};

static p* p1 = new p();
static p p2;

int main() {
    // your code goes here
    std::cout << *(p1->q);
    std::cout << *(p2.q);

    delete p1;
}

p1 and p2 are static vars, they have to stored in static segment.

  1. since p1 is a pointer, is only the pointer address stored in static segment or even the object it points to?

  2. p2 is a normal static object, but it contains a dynamically allocated member variable q,so is q also stored in static segment?

  1. p1 is a pointer, it's stored in static segment (I am not sure it's the right term), the object or memory p1 points to is on heap.

  2. p2 is an object, it's stored in static segment. q is a pointer inside p2 , the object or memory q points to is on heap.

You have two objects which are statically allocated , a pointer named p1 and an instance of type p named p2 .

There are two places in your program where dynamic allocations can occur: in class p 's constructor and when the static variable p1 is initialized.

The statically allocated objects p1 (the pointer) and p2 (the class instance) exist as long as the program runs. It is important to distinguish the pointer p1 containing just an address from the class instance at that address. (That instance will be created at run time by new p() ). The pointer and the "pointee" can have independent lifetimes; both exist independently from each other. The pointer may exist and not point to anything, and the object created by the new p() call may exist longer than any pointer to it. 1

Here is the sequence of events which unfolds when your program starts. Initialization of static variables is specified in section 3.6.2 of the C++11 standard.

  1. Allocation of variables with static storage duration , here p1 and p2 . A working model of that is that the memory is part of the program.

  2. Zeroing of those variables. "Variables with static storage duration [...] shall be zero-initialized before any other initialization takes place." The pointer p1 as well as the memory where p2 resides now consist of bytes which are all zero.

  3. Dynamic (ie run-time) initialization of those variables in the order of their definition:

    • Initialization of the pointer p1 starts with calling new p() .
      • Memory for a new object of type p is allocated dynamically ("on the heap") with the standard allocator. The memory's contents is not initialized and unknown. The object doesn't have a name, so let's call it x .
      • x ' constructor is executed in order to initialize it.
        • The constructor assigns a value to the hitherto uninitialized member variable xq . xq is part of x and as such resides in the memory dynamically allocated before.
        • The right hand side of the assignment is another call to new , this time for an int. The standard allocator dynamically allocates memory for an int which is initialized with 100.
        • The return value of new is the memory address where the int resides, which is assigned to the int pointer xq .
      • x ' constructor returns, and new p() returns the memory address where x resides.
      • This return value is assigned to hitherto zero-initialized p1 which now points to the unnamed p instance we called x .
    • Initialization of p2 . p2 's constructor is executed which does the same thing as x 's constructor above: It calls new for an int which causes a dynamic memory allocation, initializes it with 100 and assigns the address of the int's memory location to p2.q .

The result, as far as memory locations and the relations between objects are concerned, is shown in the diagram below.

程序的内存原理图

This should help answer your questions:

  1. p1 is in the "static segment", if you want, but the object it points to has been dynamically allocated at run time by the call to new .
  2. The static object p2 does not contain "a dynamically allocated member variable q". That sentence confuses the member variable -- a pointer named q -- with the object to which q points, which is a dynamically allocated int. The member variable q is stored wherever the containing instance of class p is stored; in fact, it is the only data in that instance. (Try sizeof(p) !) The object to which any instance's member q points is always a dynamically allocated int (well, that is until some malevolent programmer assigns a different value to your public q ).


1 That would constitute a memory leak because a dynamically allocated object whose address has been lost can never be deleted by the program.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM