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 ...
随机推荐
- Mac环境下制作ubantu安装盘
前言:ubantu为Linux发行版之一,此方法亦可制作其他Linux发行版 1.在磁盘工具中将准备好的u盘格式化为Mac OS扩展(日志型),并确保分区的模式是GUID分区 2.官网自行下载uban ...
- python爬虫——web前端基础(2)
图像标记------->>>> <img>图像标记,用来在网页中显示图像.使用方法为:<img src="路径/文件名.图片格式" wi ...
- 4.高级数据过滤 ---SQL
一.AND操作符 要通过不止一个列进行过滤,可以使用A ND操作符给WHERE子句附加条件. SELECT prod_id, prod_price, prod_name FROM Products ; ...
- 【考试记录】2018 山东省队集训第一轮D4(雾)
T1题意: 给你一个$n\times m$的矩阵$B$,求它能由最少多少个形如两个向量之积$(n\times 1)\times(1\times m)$的矩阵相加得到. 题解: 考虑上界,最多需要$mi ...
- Codeforces 1114F(欧拉函数、线段树)
AC通道 要点 欧拉函数对于素数有一些性质,考虑将输入数据唯一分解后进行素数下的处理. 对于素数\(p\)有:\(\phi(p^k)=p^{k-1}*(p-1)=p^k*\frac{p-1}{p}\) ...
- Floyd判圈法
---恢复内容开始--- http://blog.csdn.net/ruoruo_cheng/article/details/53100656 ---恢复内容结束---
- NET Core 与 Vue.js 服务端渲染
NET Core 与 Vue.js 服务端渲染 http://mgyongyosi.com/2016/Vuejs-server-side-rendering-with-aspnet-core/原作者: ...
- Core中使用Razor视图引擎渲染视图为字符串 阅读目录
Core中使用Razor视图引擎渲染视图为字符串 } <!DOCTYPE html> <html> <head> <title>Render view ...
- notepad++添加到运行
1. 点击开始,输入regedit,点击回车2.在注册表中找到 HKEY_CLASSES_ROOT 下面的 Applications3.修改注册表 1).在Applications下面找到对应的程序名 ...
- 《java学习三》jvm性能优化------jconsul
利用jconsul检测线程死锁, 死锁的线程,会有 已锁定 三个字 visualVm 也在jdk里 VisualVM 是一款免费的,集成了多 ...