我们都知道C++中有三种创建对象的方法,如下:

#include <iostream>
using namespace std; class A
{
private:
int n;
public:
A(int m):n(m)
{
}
~A(){}
}; int main()
{
A a(); //栈中分配
A b = A(); //栈中分配
A* c = new A(); //堆中分配
  delete c;
return ;
}

第一种和第二种没什么区别,一个隐式调用,一个显式调用,两者都是在进程虚拟地址空间中的栈中分配内存,而第三种使用了new,在堆中分配了内存,而栈中内存的分配和释放是由系统管理,而堆中内存的分配和释放必须由程序员手动释放,所以这就产生一个问题是把对象放在栈中还是放在堆中的问题,这个问题又和堆和栈本身的区别有关:

这里面有几个问题:

1.堆和栈最大可分配的内存的大小

2.堆和栈的内存管理方式

3.堆和栈的分配效率

首先针对第一个问题,一般来说对于一个进程栈的大小远远小于堆的大小,在linux中,你可以使用ulimit -s (单位kb)来查看一个进程栈的最大可分配大小,一般来说不超过8M,有的甚至不超过2M,不过这个可以设置,而对于堆你会发现,针对一个进程堆的最大可分配的大小在G的数量级上,不同系统可能不一样,比如32位系统最大不超过2G,而64为系统最大不超过4G,所以当你需要一个分配的大小的内存时,请用new,即用堆。

其次针对第二个问题,栈是系统数据结构,对于进程/线程是唯一的,它的分配与释放由操作系统来维护,不需要开发者来管理。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时,这些存储单元会被自动释放。栈内存分配运算内置于处理器的指令集中,效率很高,不同的操作系统对栈都有一定的限制。 堆上的内存分配,亦称动态内存分配。程序在运行的期间用malloc申请的内存,这部分内存由程序员自己负责管理,其生存期由开发者决定:在何时分配,分配多少,并在何时用free来释放该内存。这是唯一可以由开发者参与管理的内存。使用的好坏直接决定系统的性能和稳定。

由上可知,但我们需要的内存很少,你又能确定你到底需要多少内存时,请用栈。而当你需要在运行时才知道你到底需要多少内存时,请用堆。

最后针对第三个问题,栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率 比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在 堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会 分 到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。

再补充几点。

平时使用容器的时候,都会直接使用上述第一种方法定义。

比如:

std::vector<TestBase> a;

那么如果a要存很大的东西,会不会爆栈呢。

其实是不会的,虽然a是在栈上分配的内存,但是a所占的栈空间是很小的。

std::cout << sizeof(a) << std::endl;

输出: 24

比如vector,无论push了多少东西,存的类有多大,都在在堆上new的,而在栈上所占用的空间就只有三个指针的大小。

当然你也可以new 一个容器。这样占用栈的空间就只有一个指针的大小了。

C++中三种创建对象的方法【转】的更多相关文章

  1. iOS——浅谈iOS中三种生成随机数方法

    ios 有如下三种随机数方法:

  2. Sql Server中三种字符串合并方法的性能比较

    文章来自:博客园-DotNet菜园 最近正在处理一个合并字符吕的存储过程,在一个测试系统的开发中,要使用到字符串合并功能,直接在Sql中做.示例:有表內容﹕名称  內容1     abc1      ...

  3. C++中三种传递参数方法的效率分析

    众所周知,在C++中有三种参数传递的方式: 按值传递(pass by value) #include <iostream> using namespace std; void swap(i ...

  4. 转 java中5种创建对象的方法

    作为Java开发者,我们每天创建很多对象,但我们通常使用依赖管理系统,比如spring去创建对象.然而这里有很多创建对象的方法,我们会在这篇文章中学到. Java中有5种创建对象的方式,下面给出它们的 ...

  5. iOS-浅谈iOS中三种生成随机数方法

    ios 有如下三种随机数方法:

  6. 分布式环境中三种Session管理方法的使用场景及优缺点

    在分布式环境,管理Session通常使用下面三种方式: 一.Session Replication 方式管理 (即session复制)         简介:将一台机器上的Session数据广播复制到 ...

  7. JavaScript 三种创建对象的方法

    JavaScript中对象的创建有以下几种方式: (1)使用内置对象 (2)使用JSON符号 (3)自定义对象构造 一.使用内置对象 JavaScript可用的内置对象可分为两种: 1,JavaScr ...

  8. js中三种全局变量声明方法

    声明方式一: 使用var(关键字)+变量名(标识符)的方式在function外部声明,即为全局变量,否则在function声明的是局部变量.该方式即为显式声明详细如下: <script> ...

  9. C#三种创建对象方法所需时间比较。。。。。

    C#创建对象的三种方法  new().Activator.Assembly,接下来通过代码直接来看看运行的速度.... 首先,先看看三种创建对象实例的方法: //new(); public stati ...

随机推荐

  1. python_不用循环打印1-1000

    题目:屏幕上打印1-1000这1000个数, 不许使用循环语句/条件语句,不许使用?:算符. 不许在源代码中用列举输出语句的办法傻打,比如一千个print语句不行,不再赘述其他傻打行为, 大家都能领会 ...

  2. 每天一个linux命令:pwd命令

    Linux中用 pwd 命令来查看”当前工作目录“的完整路径. 简单得说,每当你在终端进行操作时,你都会有一个当前工作目录. 在不太确定当前位置时,就会使用pwd来判定当前目录在文件系统内的确切位置. ...

  3. C# 判断字符串为空有哪几种方法

    Length法:);Empty法:bool isEmpty = (str == String.Empty);General法:bool isEmpty = (str == ""); ...

  4. vue 中view层中方法的使用

    1.使用filters computed:{ }, filters: { filterA: function(value) { return value + 'wh' } }, 2.用法:  {{it ...

  5. 地形系统lod

    参考其他引擎,地形有近到远进行越来越深的lod,基本完成 下面是u3d的,觉得原理应该是一样的

  6. java项目中的路径获取,request

    java web项目中获取项目根路径(tomcat可运行的web源码的路径)的方式: 分为两种情况: 情况一: 在eclipse.inde等开发工具中获取(注:如下代码所在的类必须是控制层所在包下的类 ...

  7. nodejs npm 使用淘宝 NPM 镜像

    使用淘宝 NPM 镜像 大家都知道国内直接使用 npm 的官方镜像是非常慢的,这里推荐使用淘宝 NPM 镜像. 淘宝 NPM 镜像是一个完整 npmjs.org 镜像,你可以用此代替官方版本(只读), ...

  8. js 历史

    原文http://javascript.ruanyifeng.com/introduction/history.html JavaScript的诞生 JavaScript 因为互联网而生,紧随着浏览器 ...

  9. 通过NAT转发实现私网对外发布信息

    我们可以在防火墙的外部网卡上绑定多个合法IP地址,然后通过ip映射使发给其中某一个IP地址的包转发至内部某一用户的WWW服务器上,然后再将该内部WWW服务器响应包伪装成该合法IP发出的包. 具体的IP ...

  10. 【Spark】session 代替 SparkConf、SparkContext和SQLContext

    http://www.raincent.com/content-85-7196-1.html