阅读effective c++ 04 (30页) 提到的static对象和堆与栈对象。“不同编译单元内定义的non-local static对象”。

了解一下。

  

目录

stack与heap

1.Stack

2.Heap 或謂 system heap

3.例子

1.构造函数型 (stack)

2.new型 (heap 動態分配)

4.构造函数型 (stack)

1.stack objects 的生命期

2.static local objects 的生命期

3.global objects 的生命期

5.new型 (heap 動態分配)

heap objects 的生命期

关于new型的内存分配

1.自定义类class型

1.new:先分配 memory, 再調用 ctor

2.delete:先調用 dtor, 再釋放 memory

2.String*型

1.new:先分配 memory, 再調用 ctor

2.delete:先調用 dtor, 再釋放 memory

3.动态分配

1.動態分配所得的內存塊 (memory block), in VC​

2.動態分配所得的 array​

3.array new 一定要搭配 array delete

static对象

1.何时被初始化(构造)

1.non-local static object

2.local static object

2.两个编译单元中的non-local static object相互引用

3.解决方法


stack与heap

1.Stack

存在於某作用域 (scope) 的一塊內存空間(memory space)。例如當你調用函數,函數本身即會形成一個 stack 用來放置它所接收的參數,以及返回地址。在函數本體 (function body) 內聲明的任何變量,其所使用的內存塊都取自上述 stack。

2.Heap 或謂 system heap

指由操作系統提供的一塊 global 內存空間,程序可動態分配 (dynamic allocated) 從某中獲得若干區塊 (blocks)。


3.例子

class Complex { … };
...
{
Complex c1(1,2);
Complex* p = new Complex(3);
}

1.构造函数型 (stack)

c1 所佔用的空間來自 stack。

2.new型 (heap 動態分配)

Complex(3) 是個臨時對象,其所佔用的空間乃是以 new 自 heap 動態分配而得,並由 p 指向。


4.构造函数型 (stack)

1.stack objects 的生命期

class Complex { ... };
...
{
Complex c1(1,2);
}

c1 便是所謂 stack object,其生命在作用域 (scope) 結束之際結束。

這種作用域內的 object,又稱為 auto object,因為它會被「自動」清理。

2.static local objects 的生命期

class Complex { … };
...
{
static Complex c2(1,2);
}

c2 便是所謂 static object,其生命在作用域 (scope)結束之後仍然存在,直到整個程序結束。

3.global objects 的生命期

class Complex { … };
...
Complex c3(1,2);
int main()
{
...
}

c3 便是所謂 global object,其生命在整個程序結束之後才結束。你也可以把它視為一種 static object,其作用域是「整個程序」。


5.new型 (heap 動態分配)

heap objects 的生命期

class Complex { … };
...
{
Complex* p = new Complex;
...
delete p;
}

P 所指的便是 heap object,其生命在它被 deleted 之際結束。

class Complex { … };
...
{
Complex* p = new Complex;
}

以上出現內存洩漏 (memory leak),因為當作用域結束,p 所指的 heap object 仍然存在,但指針 p 的生命卻結束了,作用域之外再也看不到 p (也就沒機會 delete p)。


关于new型的内存分配

1.自定义类class型

1.new:先分配 memory, 再調用 ctor

Complex* pc  =  new Complex(1,2);

編譯器轉化為

Complex *pc;
void* mem = operator new( sizeof(Complex) ); //分配內存
pc = static_cast<Complex*>(mem); //轉型
pc->Complex::Complex(1,2); //構造函數


2.delete:先調用 dtor, 再釋放 memory

Complex* pc = new Complex(1,2);
...
delete pc;

編譯器轉化為

Complex::~Complex(pc); // 析構函數
operator delete(pc); // 釋放內存。其內部調用 free(pc)


2.String*型

1.new:先分配 memory, 再調用 ctor

String* ps = new String("Hello String("Hello");

編譯器轉化為

String* ps;
void* mem = operator new( sizeof(String) ); //分配內存
ps = static_cast<String*>(mem); //轉型
ps->String::String("Hello"); //構造函數


2.delete:先調用 dtor, 再釋放 memory

String* ps = new String("Hello");
...
delete ps;

編譯器轉化為

String::~String(ps); // 析構函數
operator delete(ps); // 釋放內存


3.动态分配

1.動態分配所得的內存塊 (memory block), in VC


2.動態分配所得的 array


3.array new 一定要搭配 array delete

String* p = new String[3];
...
delete[] p; //喚起3次dtor
String* p = new String[3];
...
delete p; //喚起1次dtor


static对象

C++中的static对象是指存储区不属于stack和heap、"寿命"从被构造出来直至程序结束为止的对象,程序结束时static对象会自动销毁。

这些对象包括全局对象,定义于namespace作用域的对象,在class、function以及file作用域中被声明为static的对象。

其中,函数内的static对象称为local static 对象,而其它static对象称为non-local static对象。

1.何时被初始化(构造)

1.non-local static object

全局对象,定义于namespace作用域的对象,在class及file作用域中被声明为static,函数之外的对象。

生命期起始时间:在main()函数调用之前被构造初始化。

生命期终止时间:在main()函数结束后自动被析构。

2.local static object

指函数中用static修饰符修饰的object。

生命期起始时间:在函数第一次调用时构造初始化。

生命期终止时间:在main()函数结束后自动被析构。


2.两个编译单元中的non-local static object相互引用

注意:在同一个文件或不同编译单元(不同文件)中,如果存在多个non-local static object,它们都是在主函数调用之前被构造的,但是它们之间的构造顺序时不定的。即对编译器来说,静态成员对象之间的初始化顺序和析构顺序是一个未定义的行为。

因此,不能用某个non-local static object去初始化non-local static object,无论这两个non-local static object在不在同一个编译单元中。

class FileSystem

{

public: …

std::size_t numDisks() const;

};

extern FileSystem tfs;

//另一编译单元

class Directory

{

public:

Directory(params);

};

Directory::Directory(params)

{

std::size_t disks = tfs.numDisks();//使用另一个编译单元的静态变量

}
Directory tempDir (params);

由于编译器没有定义non-local static object之间的构造顺序,所以有可能类tfs还没有被构造,所以程序可能会报错。

3.解决方法

用local static对象替换non-local static对象。

C++保证,函数内的local static 对象会在该函数被调用期间,首次遇上该对象定义式时被初始化。

class FileSystem {…};

FileSystem& tfs()

{

static FileSystem fs;

return fs;

}

//另一编译单元

class Directory {…};

Directory::Directory (params)

{

std::size_t disks = tfs().numDisks();//执行函数tfs时,对象fs肯定会被构造。

};

Directory& tempDir()

{

static Directory td;

return td;

}

stack与heap、new的内存分配、static对象。(effective c++ 04)的更多相关文章

  1. C++内存分配与对象构造的分离

    在C++中,我们基本用new(delete)操作符分配(释放)内存.new操作符为特定类型分配内存,并在新分配的内存中构造该类型的一个对象.new表达式自动运行合适的构造函数来初始化每个动态分配的类类 ...

  2. JVM的stack和heap,JVM内存模型,垃圾回收策略,分代收集,增量收集

    (转自:http://my.oschina.net/u/436879/blog/85478) 在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认 ...

  3. Java虚拟机创建对象的内存分配以及对象的内存布局

    本博文知识参考周志明<深入理解Java虚拟机> Java虚拟机在创建对象使如果进行内存分配: 1.指针碰撞 2.空闲列表 Java在多线程情况下创建对象的内存分配: Java完成对象内存分 ...

  4. JAVA基础-栈与堆,static、final修饰符、内部类和Java内存分配

    Java栈与堆 堆:顺序随意 栈:后进先出(Last-in/First-Out). Java的堆是一个运行时数据区,类的对象从中分配空间.这些对象通过new.newarray.anewarray和mu ...

  5. JVM性能优化系列-(2) 垃圾收集器与内存分配策略

    2. 垃圾收集器与内存分配策略 垃圾收集(Garbage Collection, GC)是JVM实现里非常重要的一环,JVM成熟的内存动态分配与回收技术使Java(当然还有其他运行在JVM上的语言,如 ...

  6. Netty 中的内存分配浅析-数据容器

    本篇接续前一篇继续讲 Netty 中的内存分配.上一篇 先简单做一下回顾: Netty 为了更高效的管理内存,自己实现了一套内存管理的逻辑,借鉴 jemalloc 的思想实现了一套池化内存管理的思路: ...

  7. linux环境内存分配原理 mallocinfo

    Linux的虚拟内存管理有几个关键概念: Linux 虚拟地址空间如何分布?malloc和free是如何分配和释放内存?如何查看堆内内存的碎片情况?既然堆内内存brk和sbrk不能直接释放,为什么不全 ...

  8. 【转】linux环境内存分配原理 malloc info

    Linux的虚拟内存管理有几个关键概念: Linux 虚拟地址空间如何分布?malloc和free是如何分配和释放内存?如何查看堆内内存的碎片情况?既然堆内内存brk和sbrk不能直接释放,为什么不全 ...

  9. linux环境内存分配原理 mallocinfo【转】

    转自:http://www.cnblogs.com/dongzhiquan/p/5621906.html Linux的虚拟内存管理有几个关键概念: Linux 虚拟地址空间如何分布?malloc和fr ...

  10. Android O Bitmap 内存分配

      我们知道,一般认为在Android进程的内存模型中,heap分为两部分,一部分是native heap,一部分是Dalvik heap(实际上也是native heap的一部分).   Andro ...

随机推荐

  1. 手工sql注入判断是否存在注入点

    1.加入单引号 ’提交,结果:如果出现错误提示,则该网站可能就存在注入漏洞.2.数字型判断是否有注入;语句:and 1=1 ;and 1=2 (经典).' and '1'=1(字符型)结果:分别返回不 ...

  2. 如何在 Laravel 中 “规范” 的开发验证码发送功能

    什么是ThinkSNS ? ThinkSNS(简称TS),一款全平台综合性社交系统,为国内外大中小企业和创业者提供社会化软件研发及技术解决方案,目前最新版本为ThinkSNS+(简称TS+).Thin ...

  3. VS 小插件 之 编辑器背景图片

    一.引言 不知道标题的名字我描述的是否正确哈,其实就是用VS写代码的时候,背景一般都是纯白 或者 纯黑(看主题而定),那么我前段时间发现 只需要一个VS插件,居然可以给VS设置背景图片,甚至还可以循环 ...

  4. render函数和redirect函数的区别+反向解析

    render函数和redirect函数的区别+反向解析 1.视图函数:一定是要包含两个对象的(render源码里面有HttpResponse对象)   request对象:----->所有的请求 ...

  5. Django之Form自定义验证规则

    1.数据源无法时时更新,有两种方法 方式一:重构构造方法(推荐) 方法一:重构构造方法(推荐) class ClassesForm(Form): name = fields.CharField( re ...

  6. Codeforces 1C(外接圆与正多边形)

    要点 各点肯定都在外接圆上,边越多越接近圆面积,所以要最小面积应当取可能的最少边数. 给三角形求外接圆半径公式:\(R=\frac{abc}{4S}\). 三个角度对应的圆心角取gcd即是要求的正多边 ...

  7. Netty(2)Echo

    上节介绍的是discard协议,即不给客户端返回消息.本节主要说下,echo协议,即服务端收到消息后原样返回给客户端. 为了实现此需求,只需要在DiscardServerHandler中重写chann ...

  8. 简易的开发框架(微服务) Asp.Net Core 2.0

      Asp.Net Core 2.0 + Mysql Orm + Ioc + Redis + AOP + RabbitMQ + Etcd + Autofac + Swagger 基础框架: https ...

  9. 关于Memcache的连接

    addServer 在说Memcache的长连接(pconnect)和短连接(connect)之前要先说说Memcache的addServer,Memcache的addServer是增加一个服务器到连 ...

  10. display:none和visibility:hidden v-show和v-if的区别

    隐藏元素display:none 和 visibility:hidden的区别visibility:hidden可以隐藏某个元素,但是隐藏的元素仍要占据空间,仍要影响布局display:none不会占 ...