2010-05-02 116 views
14

我注意到,有两种方法可以创建C++对象:创建C++对象

BTree *btree = new BTree; 

BTree btree; 

从我所知道的,唯一不同的是类对象是如何访问( 。 - > - >运算符),并且当使用第一种方法时,私有整数被初始化为0.

哪种方式更好,有什么区别?

你怎么知道什么时候使用一个或另一个?

+3

请参阅此处了解有关堆栈和堆栈的信息:http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap,http://stackoverflow.com/questions/ 408670/stack-static-and-heap-in-c – 2010-05-02 00:59:20

回答

0

好吧,它们被储存在不同的记忆区域。

这是一个很好的阅读。 Heap and Stack

+0

我对堆和堆栈有所了解。为什么我会在乎它放在哪里?我什么时候需要它在堆中,什么时候我需要它在堆栈中? – neuromancer 2010-05-02 00:56:09

+0

堆栈在应用程序中受到限制。堆没有限制(虚拟内存空间)。堆栈也受限于变量的范围。堆允许您传递结构而不考虑范围。 – 2010-05-02 00:57:46

+0

这种说法是错误的。请不要忽略静态内存。例如。全局(或命名空间范围)中的'BTree btree;'语句在静态内存中创建对象,这可能很有意义,特别是在内存受限的环境中(所有那些自动内存管理的语言,如Java *咳嗽*似乎都是盲目的我们..)。 – Frunsi 2010-05-02 01:13:59

5

第一种形式在堆上创建对象,而第二种形式在堆上创建对象。

当功能完成运行时,第二个将被销毁。 第一个将保持活着,直到被删除。

如果您只想使用当前范围内的对象,则第二种形式最好。你不必担心摆脱它,因为它会为你完成。另请注意,如果在堆栈上创建了类,某些库不起作用。

如果对象应该超过该功能,则新窗体是更好的选择。

32

两个差异:

  • 它们在存储器中创建的不同部分中的对象(堆VS堆栈)

  • 对象寿命是不同的: 在第一种情况中,代码管理内存分配明确,,它也必须明确地管理取消分配(使用删除/删除[])。

    在第二种情况下,该对象被自动地在其闭合范围的端部释放(或者一种方法,一种方法内的嵌套块,或一类),你使用哪一个

主要取决于在对象的生命周期中(如果它应该超过创建它的方法)。

+1

+1,我只想添加第一条和简单的经验法则:喜欢自动分配,在需要时使用显式分配,例如,一个坏例子:'void foo(){BTree * btree = new BTree; btree-> DoSomething的();删除btree; }' – Frunsi 2010-05-02 01:08:56

+0

如果该对象在main中声明,当两个方法的main都退出时它会自动被释放吗? – neuromancer 2010-05-02 01:32:28

+0

在程序结束之前未被删除的堆分配对象(使用'new')本身不会被“解除分配”。例如,它的析构函数将不会因程序结束而被调用。但是,该对象使用的内存将返回到操作系统。在现代操作系统下运行的程序无法在退出后继续使用内存,无论它有多严重的泄漏。 – 2010-05-02 01:50:53

2

高级别区别是对象生存期。例如,如果您正在编写视频游戏,您将通过new分配与堆上的怪物对应的对象。这样,怪物的基础物体就像怪物一样生活,这在编写程序时是不可知的。当玩家杀死怪物时,你的代码可以使用delete销毁怪物物体。

另一方面,您将使用另一种形式的总分计数器,因为您知道计数器需要多长时间(大概只要游戏正在运行!)。通过将这种形式放在任何函数体外的“全局范围”中,它将被静态分配,作为程序二进制本身的一部分。

最后,如果你计算数组的总和,是这样的:

int mysum(int* arr, int len) { 
    int sum = 0; 
    for (int i = 0; i < len; ++i) { sum += arr[i] } 
    return sum; 
} 

sum变量堆栈,这基本上是你想要什么就分配:你不要临时变量必须显式释放,并且只在该函数实际运行时才会执行。

3

这两种形式的另一个区别是分配这些对象的存储时间。表格BTree bTree;命名为静态分配,其分配在编译时完成 - 即编译器将在运行时为内存中的此对象安排内存空间。而所谓的动态分配BTree *pbTree = new BTree的分配 - 在运行时执行 - 即只有当正在运行的程序到达此点时才会分配momory。

在这种情况下,静态和动态分配之间的差异并不明显。考虑以下情况:需要为整数数组分配内存空间,但是只能在运行时确定元素的数量,即我们只能知道程序开始执行后数组所占用的确切内存空间。

// in this function, we want to return a copy of the parameter array 
int *array_cpy(int *arr, int num){ 
    int *copy = new int[ num ]; 

    int i; 
    for(i = 0; i < num; i++){ 
     copy[ i ] = arr[ i ]; 
    } 

    return copy; 
} 

这里定义int copy[ num ];是不恰当的,其中一个原因是我所上述,另一种是copy寿命活得比的功能。但是,鉴于最近的语言规范允许VLA,第二个原因是这个问题的关键。

3

在你是应该堆栈还是堆分配内存之间进行选择时,你需要仔细研究两者之间的差异。

是的,堆栈内存具有在超出范围时自动释放的优点,但通过智能指针和堆分配也可以实现同样的效果。更重要的是为什么发生这种情况的原因。

性能: 堆栈内存被自动清除,因为它涉及内存超出范围时栈指针的简单移位。由于这个原因,堆栈内存的分配和释放比堆内存快得多。

内存使用期限: 堆分配内存超出了分配函数的范围。堆栈不是。从上面关于调整堆栈指针的推理出发,一旦内存被解除分配,它是空闲的并且很可能被覆盖以用于下一个堆栈分配。

简而言之,当分配是临时的时候使用堆栈内存,特别是如果您需要重复分配并且性能很重要。当对象需要超出分配方法时使用堆内存。