繁体   English   中英

C ++:静态指针,静态对象和动态内存分配

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

考虑下面的代码段:

#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和p2是静态变量,它们必须存储在静态段中。

  1. 由于p1是指针,因此仅将指针地址存储在静态段中还是指向它的对象中?

  2. p2是一个普通的静态对象,但是它包含一个动态分配的成员变量q,q也存储在静态段中吗?

  1. p1是一个指针,它存储在静态段中(我不确定这是正确的术语), p1指向的对象或内存在堆上。

  2. p2是一个对象,它存储在静态段中。 qp2内的指针, q指向的对象或内存在堆上。

您有两个静态分配的对象,一个名为p1的指针和一个名为p2的类型p的实例。

程序中有两个地方可以进行动态分配:在类p的构造函数中,以及在初始化静态变量p1

只要程序运行,静态分配的对象p1 (指针)和p2 (类实例)就存在。 将仅包含一个地址的指针p1与该地址处的类实例区分开是很重要的 (该实例将在运行时由new p() )。 指针和“指针”可以具有独立的生存期; 两者彼此独立存在。 指针可能存在而不指向任何东西,并且由new p()调用创建的对象的存在可能比指向它的任何指针的存在时间都长。 1

这是程序启动时发生的事件序列。 静态变量的初始化在C ++ 11标准的3.6.2节中指定。

  1. 具有静态存储持续时间的变量的分配,此处为p1p2 一个有效的模型是内存是程序的一部分。

  2. 这些变量归零。 “具有静态存储持续时间的变量应在进行任何其他初始化之前进行零初始化。” 指针p1以及p2所在的内存现在由全为零的字节组成。

  3. 按定义顺序对这些变量进行动态(即运行时)初始化

    • 指针p1初始化从调用new p()
      • 使用标准分配器动态地(“在堆上”)分配类型为p的新对象的内存。 内存的内容未初始化且未知。 该对象没有名称,因此我们将其称为x
      • 执行x '构造函数以对其进行初始化。
        • 构造函数将一个值分配给迄今尚未初始化的成员变量xq xqx一部分,因此驻留在之前动态分配的内存中。
        • 赋值的右边是对new另一个调用,这次是int。 标准分配器为初始化为100的int动态分配内存。
        • new的返回值是int所在的内存地址,该地址分配给int指针xq
      • x '构造函数返回,而new p()返回x所在的内存地址。
      • 此返回值分配给迄今为零初始化的p1 ,该p1现在指向我们称为x的未命名p实例。
    • p2初始化。 p2的构造函数被执行,其功能与上述x的构造函数相同:它对int调用new ,该int会导致动态内存分配,将其初始化为100并将int内存位置的地址分配给p2.q

下图显示了有关内存位置和对象之间关系的结果。

程序的内存原理图

这应该有助于回答您的问题:

  1. 如果需要, p1在“静态段”中,但是它指向的对象已在运行时通过对new的调用而动态分配。
  2. 静态对象p2 包含“动态分配的成员变量q”。 该语句使成员变量(名为q的指针)与q指向的对象动态分配的int)混淆。 成员变量q存储在存储类p的包含实例的任何位置; 实际上,它该实例中的唯一数据。 (尝试sizeof(p) !)任何实例的成员q指向的对象始终是动态分配的int(嗯,直到某个恶意的程序员为您的public q分配了不同的值)。


1这将构成内存泄漏,因为该程序永远无法删除其地址已丢失的动态分配的对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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