我用MFC建一个Dialog,发现在OnInitDialog里(都是局部的):
1.用CButton bt; bt.Create(...);    Button不会显示出来.内存东西变了.
2.用CButton* bt=new CButton;bt->Create(...);   Button会显示出来.问题1.bt怎么不会出来,是不是就是bt是在 全局静态内存 中?是由系统给释放了吗?如果是由系统释放了,那么看第二题,不是,那么说明是什么
问题2.如果是,那么,看这里
void init()
{
char* szText="ddd";//这里"ddd"是分配在全局静态内存中的,且把地址给了szText;那么这个函数结束后为什么这个内存还有值呢,即原始"ddd"的那部分空间还存在刚才的值(而不是szText,这里是用Debug中的Memory窗口看的)?
}
问题3.如声明了char* szText;....那么用过后要我们自己释放.那么,声明了int* p=new int;*p=1;呢,这是不是还得我们自己释放呀(int型的太简单了,有点迷糊,不知道是不是要释放,这里这个int指针也是在动态内存区的吗?)?

解决方案 »

  1.   

    1,bt是局部变量,OnInitDialog函数执行完它就释放了啊,当然不会显示出来,第二个指针的那个由于内存是由你控制的,里面的数据只要在程序生命周期中你没给它delete它会一直存在的,所以Button也会显示
    2,这种方式也相当于你new了一块内存来存"ddd",所以你没delete里面的数据也还是存在的
    3,这个还是一样,只要new了,就要去delete不管是什么类型,否则内存泄漏
      

  2.   

    2楼正解,局部变量的作用范围是局部的,超出范围就释放了,而用new开辟的内存就能在程序生命周期里存在,除了用delete之。
      

  3.   

    1、函数中定义的局部(动态)变量是在栈中分配的,在函数返回时会自动释放(类对象会自动析构)。
    2、"ddd"是常量,不是动态变量,是不能释放的。szText是指针变量,函数返回时释放的是这个变量,不是释放其指向的内存。
    3、同2。
      

  4.   

    第一个问题可没有那么简单:定义一个局部变量:{
     ...
     CButton bt;
     bt.Create(...
     ...
    }
    是的,函数返回时变量 bt 的生命期就结束了,这个没错;但为什么建立的按钮也没有了呢?不知道为什么,有兴趣的朋友可以研究一下,
    这有助于你更好的理解 C++ 对象 和 窗口对象。
      

  5.   


    1.如下:
    #include "stdafx.h"
    #include <string>
    void add()
    {
    char *szChar1="www";
    int nIndex=6;
    }
    int main(int argc, char* argv[])
    {
     add();
     char *szChar2="yyy";
     return 0;
    }我做了测试,不一定正确,但结果如下(Debug,用Memory查看当前内存):
    由add()进入,查到内存区的szChar1: 0x0042201c(查Memory,值是"www")
    &nIndex: 0x0012ff20(查Memory,值是6)add()执行完毕,到 char *szChar2="yyy"; 
    我同样根据刚才记录的那些变量地址
    0x0042201c(值还是"www"),
    0x0012ff20(值还是6)
    问题4:这说明了什么呢?是没有释放吗(什么是释放呢,是要==NULL或其它的吗)?还是其它什么?是这样说的吗?那么我用下面的代码会错的,注释是我自己的理解char *szChar1="www";
    delete []szChar1;//1.因为我没有new,这个"www"是在静态内存中的,是不能更改的,所以delete会出错,如果用下面的就没有错了char *szChar1=new char[3];
    strcopy(szChar1,"ddd");
    delete []szChar1;//2.这里没报错,因为它用的是自己申请的空间,自己delete没有问题不对的地方还请指出
      

  6.   

    模块卸载的时候。如果是exe程序中的常量,就是整个程序结束的时候。
      

  7.   

    呵呵,我这么说只是做个类比,又不是真让你去delete,delete和new是成对用的,分开用肯定是不行的。char *szChar1="www";这样的方式会产生内存问题,因为它无法去delete,你测试时也应该看到了,所以写程序的时候很少会用这种方式去初始化一个字符串,都是用字符数组的方式的。
      

  8.   


    #include <string>
    class classNew
    {
    public:
    classNew(){y=1;};
    ~classNew(){};
    public:
    int y;
    };
    void add()
    {
    classNew cN;//记录地址&cN(内存查看);
    int nIndex=2;//记录地址&nIndex,也就是2的地址(内存查看);
    }
    int main(int argc, char* argv[])
    {
    add();
    int test=1;//检&cN和&nIndex刚记录的地址数据是否更改(内存查看)

    return 0;
    }
    结果,&cN的内存是在离开add函数体后,改变了,但&nIndex这个内存区还没有改变,为什么呢?
      

  9.   


    &cN地址变了那是类的析构函数析构的结果,&nIndex没有变因为它只是普通变量地址,没类似析构函数的操作,地址是不会改变的,但里面的值1肯定是没了
      

  10.   

    这句话也看了N遍了,现在有点明白了.那问下,Debug和"编译完成"是什么关系
    1.Debug就是在执行编译,即编译没有完成.
    2.能Debug就说明已经编译完成了.1,2两种关系是哪 个呢,要是第一个,那么说对了,要是第二个.就有问题了
      

  11.   

    我Debug时,还没有运行到那add里,但我Memory看那个地址,没有值.如果,是我说是我说的第二种情况,那么这个就对了.
      

  12.   

    你按F7,那就是编译。按F5就是开始Debug。如果代码变了,不按F7直接按F5,那么会默认先编译,然后Debug。"我Debug时,还没有运行到那add里,但我Memory看那个地址",你说的Memory看的那个地址是哪个?实际上"ddd"在程序被加载到内存后就已经存在了。如果没看到,那么是你看错地址了。
      

  13.   

    我确定没有看错
    我是Debug了两边,先Debug到
    int nIndex=2;//记录地址&nIndex,也就是2的地址(内存查看);
    然后记住&nIndex人地址。然后,停止Debug,再第二次Debug,还用刚才的地址。在没有运行到
    int nIndex=2;//记录地址&nIndex,也就是2的地址(内存查看);
    的时候,看一下刚才的地址,没有,然后运行到
    int nIndex=2;//记录地址&nIndex,也就是2的地址(内存查看);
    发现变化了,这时候为了确认刚才的地址和现在的地址是一样的,我还是看了&nIndex,和刚才的一样
    所以地址是没有错误,两次的一样。
      

  14.   

    char *szChar1="www"; //这个是字符串字面值,www在静态存储区,程序结束后,自动释放
    char szChar1[] = "www";//局部变量,分配在栈上,离开作用域后,自动释放CButton bt; bt.Create(...);    //局部变量,分配在栈上,离开作用域后,自动释放
    char *szChar1=new char[3]; //new动态内存分配,分配在堆上,需要开发人员自己用delete手动释放
      

  15.   

    谢谢,终于明白这点的意思了:
    1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
    2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
    3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放 
    4、文字常量区—常量字符串就是放在这里的。 程序结束后由系统释放
    5、程序代码区—存放函数体的二进制代码。