2
int globalInt = 1; 

int main(){
    int* heapInt = new int(1);
}

globalInt 和 heapInt 有什么区别?我知道 heapInt 指向的是堆中,我知道 globalInt 进入一些全局数据存储,但是有什么区别呢?为什么要使用一个而不是另一个?

预先感谢您的任何帮助。

4

3 回答 3

4

全局变量具有静态存储持续时间。这意味着对象从程序开始到结束都存在。它在整个程序期间都存在。

使用intnew-expression 创建的具有动态存储持续时间。它的生命周期从 new-expression 开始,在你 do 时结束delete heapInt;

您可以将这两个存储持续时间视为频谱的两端。全局变量使您对其生命周期的控制最少,因为它始终存在。动态分配的对象为您提供最大的控制权,因为您可以在代码中的任何位置创建和销毁它。

还值得注意的是,全局变量有一个名称。这使得该名称在范围内的代码的所有部分都可以访问该对象。相反,要访问动态分配的对象,您需要获得指向它的指针。

全局变量通常被认为是不好的做法,因为它们将全局状态引入您的程序。也就是说,您可能有一个修改或使用全局变量的函数,而没有明确说明它在其接口中这样做。这意味着该函数可能有秘密的副作用,导致难以测试的不可预测和不可维护的代码。

另一方面,动态分配的对象通常是必要的,但应谨慎使用。确保对象的生命周期得到适当管理是很重要的。一种方法是使用RAII,其中对象仅在构造函数中动态分配,然后在析构函数中相应地销毁。另一种现代方法是避免完全自己进行内存管理,而是使用智能指针。

于 2013-05-19T23:25:05.577 回答
1

有两个主要区别 - 范围和生命周期。

您可以globalInt在程序中的任何地方使用,而您heapInt只能在main.

全局的生命周期是从程序开始(好吧,因为main无论如何都进入之前)到结束,而动态分配的生命周期在您启动时开始,在您启动时new消失delete

于 2013-05-19T23:28:49.247 回答
0

只是为了烤你的面条,你是否也考虑过

int globalInt = 1;
int* globalHeapInt = new int(1);

int main() {
    int* heapInt = new int(1);
}

回答为什么部分:在堆中存储任何东西都会产生指针的开销 - 4 或 8 个字节,具体取决于您要构建的位数。

诸如用于普通数据类型的 globalInt 之类的全局值被写入可执行文件的“数据段”,并在操作系统启动应用程序时以硬连线方式加载到进程中。

globalHeapInt 将加载 NULL 值,然后在编译器提供的一些秘密引导“pre-main”代码中,程序将不得不执行:

globalHeapInt = malloc(sizeof(int));
*globalHeapInt = 1;

在 64 位系统上,您现在使用(至少)12 个字节来存储一个 4 字节的值。

“heapInt”执行类似的操作,但指针存储在堆栈或寄存器中。

为什么要使用全局值?当您拥有有限的已知数据量时,将它们放在简单的全局变量中是有意义的。

因此,堆主要用于动态存储 - 当您事先不知道是否需要或需要多少时。例如,想象一个将书籍列表作为命令参数的程序:

// reserve memory for upto 1000 Books.
Book globalBooks[1000];

// or use the heap when we know how many we need.
int main(int argc, const char* argv[])
{
    int numBooks = argc;
    if ( numBooks < 1 ) {
       printf("Screw you and your empty book list.\n");
       exit(1);
    }
    Books* heapBooks = new Books(numBooks);
    ...
}

第一种形式只能处理 1000 本书,但它始终可以存储多达 1000 本书。第二种形式可以处理任意数量的书籍,直至进程可用的最大内存量。

于 2013-05-20T01:46:46.490 回答