根据我的学习,需要使用delete运算符删除动态分配的变量,并且不会在范围的末尾自动删除,就像静态变量一样。
因此,在以下示例中,当循环运行第2次和第3次时,不应该“int * p = new int;”由于动态分配的内存“p”尚未被删除,因此被认为是多次初始化?
#include<iostream>
using namespace std;
void main()
{
int i = 2;
while (i > -1)
{
int *p=new int;
*p = 5;
cout << *p;
--i;
}
}
使用Visual Studio 2015,上述程序不会出错。根据我的理解,这没有意义。
我认为我对动态分配变量的理解有问题。有人可以澄清一下吗?
答案 0 :(得分:1)
您的代码显示了所谓的&#34;内存泄漏&#34;。当p
超出范围而没有首先delete
内存时,为每个循环迭代分配的内存将丢失。这(通常)不会导致编译器警告或运行时错误,因为编译器找到这种错误可能会非常复杂。一些静态代码分析器可能能够检测到这一点。
在内存泄漏的情况下,您可能会注意到,程序运行的时间越长,内存越来越多,这意味着内存泄漏在RAM较低的系统和长时间运行的程序中尤其成问题。系统服务应该运行几天。
有一些特殊的工具可以找到内存泄漏,例如:适用于Linux的valgrind或Visual Studio的调试运行时中的内置工具。
答案 1 :(得分:0)
您不能动态分配变量,只能分配对象。
p
不是动态分配的对象,但*p
- 由new
创建的对象 - 是。
delete p
不会删除p
,而是删除它指向的对象。
Scope是一个适用于名称的语法编译时属性。
具有名称的变量p
具有范围
它指向的对象是未命名的,因此范围的概念甚至不适用于它。
在运行时,p
和它指向的对象都有生命周期。
p
的生命周期与其范围一致,因为它是一个自动变量。循环的每次迭代都有自己的变量,所有变量都具有相同的名称 - 没有多次初始化,因为变量是不同的。
p
指向的对象的生命周期,直到其地址传递给delete
为止。
由于您从未这样做,因此使用new
“创建的每个对象都会泄漏”。
答案 2 :(得分:0)
p 只是一个包含动态数据地址的静态变量,指针本身在作用域结束时丢失,而动态数据在没有指针访问的情况下持续存在(内存泄漏)。
p 指向的数据是动态内存(在堆中),每次迭代后都不会被释放,但是,变量 p 本身的内容(这是动态数据的地址,如果你去 p在内存中,您会发现它是堆栈中的一个简单数字,它只是堆中动态数据的地址,而不是数据本身)只是堆栈中的一个静态地址,它在作用域结束时丢失(迭代)。