stack与heap、new的内存分配、static对象。(effective c++ 04)
阅读effective c++ 04 (30页) 提到的static对象和堆与栈对象。“不同编译单元内定义的non-local static对象”。
了解一下。
目录
1.動態分配所得的內存塊 (memory block), in VC
3.array new 一定要搭配 array delete
2.两个编译单元中的non-local static object相互引用
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)的更多相关文章
- C++内存分配与对象构造的分离
在C++中,我们基本用new(delete)操作符分配(释放)内存.new操作符为特定类型分配内存,并在新分配的内存中构造该类型的一个对象.new表达式自动运行合适的构造函数来初始化每个动态分配的类类 ...
- JVM的stack和heap,JVM内存模型,垃圾回收策略,分代收集,增量收集
(转自:http://my.oschina.net/u/436879/blog/85478) 在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认 ...
- Java虚拟机创建对象的内存分配以及对象的内存布局
本博文知识参考周志明<深入理解Java虚拟机> Java虚拟机在创建对象使如果进行内存分配: 1.指针碰撞 2.空闲列表 Java在多线程情况下创建对象的内存分配: Java完成对象内存分 ...
- JAVA基础-栈与堆,static、final修饰符、内部类和Java内存分配
Java栈与堆 堆:顺序随意 栈:后进先出(Last-in/First-Out). Java的堆是一个运行时数据区,类的对象从中分配空间.这些对象通过new.newarray.anewarray和mu ...
- JVM性能优化系列-(2) 垃圾收集器与内存分配策略
2. 垃圾收集器与内存分配策略 垃圾收集(Garbage Collection, GC)是JVM实现里非常重要的一环,JVM成熟的内存动态分配与回收技术使Java(当然还有其他运行在JVM上的语言,如 ...
- Netty 中的内存分配浅析-数据容器
本篇接续前一篇继续讲 Netty 中的内存分配.上一篇 先简单做一下回顾: Netty 为了更高效的管理内存,自己实现了一套内存管理的逻辑,借鉴 jemalloc 的思想实现了一套池化内存管理的思路: ...
- linux环境内存分配原理 mallocinfo
Linux的虚拟内存管理有几个关键概念: Linux 虚拟地址空间如何分布?malloc和free是如何分配和释放内存?如何查看堆内内存的碎片情况?既然堆内内存brk和sbrk不能直接释放,为什么不全 ...
- 【转】linux环境内存分配原理 malloc info
Linux的虚拟内存管理有几个关键概念: Linux 虚拟地址空间如何分布?malloc和free是如何分配和释放内存?如何查看堆内内存的碎片情况?既然堆内内存brk和sbrk不能直接释放,为什么不全 ...
- linux环境内存分配原理 mallocinfo【转】
转自:http://www.cnblogs.com/dongzhiquan/p/5621906.html Linux的虚拟内存管理有几个关键概念: Linux 虚拟地址空间如何分布?malloc和fr ...
- Android O Bitmap 内存分配
我们知道,一般认为在Android进程的内存模型中,heap分为两部分,一部分是native heap,一部分是Dalvik heap(实际上也是native heap的一部分). Andro ...
随机推荐
- angular实现表格的分页显示
最近项目中用到了一个功能,就是表格的分页显示.以前没整过,今天学会了,把它整理一下,下次可以直接用. 实例代码:https://github.com/dreamITGirl/projectStudy ...
- 阿里云ECS测试服务器部署
前序:为了提供一个干净的测试环境,更好地验证产品问题,也为了防止被开发人员频繁发布代码而打断测试工作,故测试团队搭建了一台阿里云ECS服务器,以下是具体的部署信息: 1. 安装JDK Java版本:J ...
- Spring Cloud Hystrix理解与实践(一):搭建简单监控集群
前言 在分布式架构中,所谓的断路器模式是指当某个服务发生故障之后,通过断路器的故障监控,向调用方返回一个错误响应,这样就不会使得线程因调用故障服务被长时间占用不释放,避免故障的继续蔓延.Spring ...
- EasyPOI 教程以及完整工具类的使用
因为项目的原因需要用到POI来操作Excel 文档,以前都是直接使用POI来操作的,但是最近听到easypoi的存在,所以自己简单的尝试了下! 别说,他还真的挺好用的 Easypoi介绍 Easypo ...
- Codeforces Round #432 (Div. 2, based on IndiaHacks Final Round 2017) C
You are given set of n points in 5-dimensional space. The points are labeled from 1 to n. No two poi ...
- Spring Boot Security配置教程
1.简介 在本文中,我们将了解Spring Boot对spring Security的支持. 简而言之,我们将专注于默认Security配置以及如何在需要时禁用或自定义它. 2.默认Security设 ...
- 用于<挣值管理>的各种指标计算
PV(Planning Value) 含义:计划价值,截至到某个时间计划工作经批准的成本预算. 公式:PV=计划工作数X计划单价. BAC 含义:完工预算,截至到完工时间计划工作经批准的成本预算,即完 ...
- keil下JLINK在线调试仿真设置,SWD连接
keil下JLINK在线调试仿真设置,以下三个步骤搞定: 有时我们编译时会遇到空间不足的情况,首先我们应该把 flash和RAM的size 设置为当前所用芯片的大小,如下我使用了一个片上flash 2 ...
- azure powershell 获取可用镜像列表
通过Azure Powershell 指定location和Pbulishername 获取所有可用镜像的 publisherName,Offer,Skus,Version,location信息列表 ...
- {Linux} boot仅剩余XX字节
1. 查看已安装的linux-image各版本 dpkg --get-selections |grep linux-image 2. 查看我们当前使用的是哪一个版本: uname -a 3. ...