C++旧源码向新标准移植陷井(一)_局部栈变量的生命周期

之前在VC++6.0上面写了下面这样的代码:

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    int nRetCode = 0;
   //不重要的部分略过if (argc>1)
        {if (strcmp(argv[1],"createpcsstep") == 0)
                {
                    CDlgCreateStepPcs dlg;
                    dlg.DoModal();
                    break;
                }
                else if (strcmp(argv[1],"clearunless") == 0)
                {
                    CDlgClearUnless dlg;
                    dlg.DoModal();
                    break;
                }
          //还有很多这样的弹对话框,都省略了吧,只留两个else {}
        }
    }
    return nRetCode;
}

很明显这是一个控制台程序,启动根据条件判断弹出一个对话框,这段代码在VC6.0中编译,运行无任何问题;

后来照这个代码流程移植成VS2008 + QT sdk重新编译,发现对话框是一闪而过,想了好久,硬是不知道问题出在哪里,可把我郁闷的够呛,经过多次的把代码移动试验,突然想到是变量的生命周期问题,想到这点就豁然开朗了,VS2008使用了新的C++标准,在新标准中C++规定{}中的变量只在这个块中有效,出了块就被析构了(类是被析构),因此Qt中正确的代码顺序是这样的:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QDialog *pDlg = NULL;  //新的C++标准中,不能在if块中声明对像,否则出了块就被析构了
    if (argc > 1)
    {
        if (strcmp(argv[1],_SCRIPTS_NAME_OUTPUTGERBER) == 0)
        {
            pDlg = new DlgOutputGerber;
             pDlg->show(); //造成问题的关键在这里,不同于MFC,这里执行完了还要继续向下进入到a.exec()消息循环
        }
    }
    int nRet = a.exec();
    if (pDlg != NULL) delete pDlg;
    return nRet;
}

见上面的所述的关键点,如果是像前面那样在if块里面声明一个Dialog对像,show()完之后就要出块进入a.exec(),但这样一旦出块,Dialog对像就已经被析构了,因些窗口一闪而过.

我在这里采用的方法是,块外面定义一个指针,if块里面在堆上实例化一个Dialog对像,完美解决此问题.

原文地址:https://www.cnblogs.com/guobbs/p/3889628.html