我注意到创建C++对象有两种方式:
BTree *btree = new BTree;
并且
BTree btree;
据我所知,唯一的区别在于如何访问类对象(. vs. ->运算符),以及当使用第一种方式时,私有整数将被初始化为0。
哪种方式更好,有什么区别?
你如何知道何时使用其中一种?
两者的不同之处:
它们在内存中的不同部分创建对象(heap vs stack)。
对象的生命周期是不同的: 在第一种情况下,代码显式地管理内存分配,并且必须显式地管理内存释放(使用delete/delete[])。
在第二种情况下,对象在其封闭范围的末尾自动释放(可以是方法、方法内的嵌套块或类)。
你使用哪个取决于对象的生命周期(是否应该在创建它的方法之外存在)。
void foo() { BTree* btree=new BTree; btree->DoSomething(); delete btree; }
。 - Frunsinew
分配在堆上的对象,如果在程序结束之前没有被删除,它不会被“释放”。例如,当程序结束时,它的析构函数不会被调用。但是,该对象使用的内存将返回给操作系统。无论内存泄漏有多严重,运行在现代操作系统下的程序都无法在退出后继续消耗内存。 - Tyler McHenryBTree bTree;
的静态分配方式会在编译时完成其分配,也就是说编译器将在运行时为该对象安排内存空间。而使用BTree *pbTree = new BTree
的动态分配方式则是在运行时完成其分配,也就是只有当程序执行到这一点时才会分配内存。// 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,第二个原因成为了解决这个问题的关键。
new
在堆上分配与怪物对应的对象。这样,怪物的底层对象的生命就与怪物本身一样长,而在编写程序时是不可知的。当玩家杀死怪物时,你的代码可以使用delete
销毁怪物对象。int mysum(int* arr, int len) {
int sum = 0;
for (int i = 0; i < len; ++i) { sum += arr[i] }
return sum;
}
sum
变量是分配在堆栈上的,这基本上是你想要的:一个临时变量,你不需要明确地释放它,并且只有当该函数实际运行时才存在。
嗯,它们被存储在内存的相当不同的区域。
这是一篇很好的阅读材料。 堆和栈
BTree btree;
语句会在静态内存中创建对象,这在内存受限的环境中非常有意义,尤其是在所有那些自动内存管理语言(像 Java 咳咳)似乎让我们失明的情况下。 - Frunsi