混沌 IN C++::Exception思维

原创 2004年07月11日 21:20:00

难度:star.gifstar.gifstar.gifstar.gif

您的代码中有Exception吗?作为C++中最具争议的东西,就连在使用上也不是一件容易的事,您怎么看待异常呢?<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

如果想判断一个对象是否构造成功,我们可以用以下的三种方法

1

struct A

{

A(int& i)

{

    //其他代码

    if(构造失败)

         i = 0;

     else

         i = 1;

}

};

 

int i;

A a(i);

if(i==0)

cout<<构造失败<<endl;

 

2

class A

{

public:

     A()

{

        //其他代码

        if(构造失败)

              isok_ = false;

        else

              isok_ = true;

}

bool isok() const

{  return isok_; }

private:

     bool isok_;

};

 

A a;

if(!a.isok())

     cout<<构造失败<<endl;

 

3

class my_exception: public std::exception{};

 

struct A

{

A()

{

    //其他代码

    if(构造失败)

        throw my_exception();

}

};

 

try

{

    A a;

}

catch(my_exception& ex)

{   cout<<构造失败<<endl; }

 

综观三种方法,我们来做个简单的分析。

第一种,该构造函数提供了一个用于返回错误的标志变量,虽然可以判断是否构造成功,但是这个多余的变量更像是一个累赘。

第二种,构造函数上没有歧义了。但是它并没有降低复杂度。更重要的是,它和第一种方法有个通病,那就是析构函数会被正常调用。换句话说,这样的对象构造失败并不是语言所支持的,而是程序员自己的逻辑规定。

第三种,这就完全没有上面两种方法的问题,在构造函数中抛出异常,就意味这这个对象未构造成功,这是被语言所支持的,这样一来,class A的析构函数将不会作用于对象a。这一特性可以让我们不再为这类安全性操心了。

 

在某些函数中,我们可以通过按值返回错误码,但在某些情况下这类方法并不顶用,这样我们就可以考虑异常。

 

从上面的表现来看,并没有体现出异常带来复杂度。但是,当遇到资源管理时,其中就有很多事情也许会被我们忽略。

void test()

{

int* p= new int;

//其他代码

    delete p;

}

 

如果中间的代码抛出异常,最好的情况就是内存泄露及带来不安全因素。我们应该加入异常处理

void test()

{

int *p =NULL;

try

{

    p = new int;

    //其他代码

}

catch(...)

{

    delete p;

    throw; //异常中立,保证了前一版本test函数的行为

}

    delete p;

}

但这也许并不算最爽的解决方案。我们可以利用RAII技巧。来简化这个操作

template<typename T>

class auto_new

{

public:

      auto_new():ptr_(NULL)

      {

           try

           {

                  ptr_ = new T;

           }

           catch(std::bad_alloc)

           {

    //异常处理

}

}

~auto_new()

{

    delete ptr_;

}

operator T*()

    {  return ptr_; }

private:

      T* prt_;

}

 

void test()

{

     auto_new<int> p;

     //其他的代码

}

这样就不用担心异常发生时带来的资源回收问题。当然,对于简单的资源,我们可以采用auto_ptr<>

也许各位看官会认为,这样的做法也并没有降低复杂度,似乎反而增大了工作量。是的,但是这样的代码可以使我们更放心。

 

异常也不是十全十美的,它自身也存在很多的缺陷,比如它的运行成本比较高,如果正常的控制结构可以处理错误,那么就不应该去使用异常。异常的一个作用就是当某个部分出现异常状况,那么我们可以通过异常来通知另一个部分。例如,当程序出现异常,那么我们可以把这个异常层层往上传递到函数的调用点,而其他的错误处理方式并不这么方便。虽然异常可以在两个部分进行传递,但是它并不是跨线程的,我们不能在两个线程间传递异常。例如下面的代码就是错误的

 

DWORD CALLBACK threadfunc(void*)

{

   //其他代码

   throw int();  //抛出异常

}

 

int main(){

    try

    {

        DWORD tid;

        HANDLE hdl = CreateThread(NULL, 0, &threadfunc, NULL, 0, &tid);

        Sleep(500);

        CloseHandle(hdl);

    }

    catch(...)

       {  cout<<"catched"<<endl;}

}

 

threadfunc抛出的异常我们根本无法接收到。这样也说明了一个问题,当我们不确定线程函数中的代码是否会抛出异常的时候,我们都必须在其中加入try 块,以保证异常安全。例如上面的代码就应该写成下面这个样

 

DWORD CALLBACK threadfunc(void*)

{

   try

   {

      //其他代码 //不确定这里是否会抛出异常

   }

   catch(...)

   {}

}

 

int main(){

     DWORD tid;

     HANDLE hdl = CreateThread(NULL, 0, &threadfunc, NULL, 0, &tid);

     Sleep(500);

     CloseHandle(hdl);

}

 

//The End

Logistic混沌序列加密

Logistic混沌置乱,先不说有多复杂,其实很简单。 Logistic函数是源于一个人口统计的动力学系统,其系统方程形式如下:  X(k+1) = u * X(k) * [1 - X(k...
  • qq_23291783
  • qq_23291783
  • 2016年01月29日 09:48
  • 1392

蔡氏电路混沌同步Multisim实现

前言:关于蔡氏电路混沌同步的文献网上很多,因此只给出具体实现方案。课程作业,仅供参考 1.   非线性负电阻的搭建 利用Multisim搭建如下: 图1 负电阻电路 图1所示负电阻由两个负电...
  • chenjianbo88
  • chenjianbo88
  • 2015年12月28日 15:28
  • 1828

【图像加密】图像处理之Logistic混沌序列加密

Logistic混沌序列加密。
  • hujingshuang
  • hujingshuang
  • 2015年05月14日 10:54
  • 3567

混沌IN C++::所谓的隐晦

难度:   很多人抱怨C++有太多隐晦语法的问题。今天,来谈两个隐晦的语法问题。   一,关于Declarator。 有时候,我们会故意制造一个便于理解的编译错误。 ...
  • ibmmicrosoft
  • ibmmicrosoft
  • 2011年12月11日 17:50
  • 957

Effective Exception Handling in Visual C++译

  • 2012年11月05日 09:28
  • 323KB
  • 下载

Effective Exception Handling in Visual C++

Effective Exception Handling in Visual C++ 在C++中进行有效的异常处理   出自CodeProject,原文链接:http://www.codepro...
  • qyfcool
  • qyfcool
  • 2012年11月04日 20:03
  • 1450

关于错误 Unhandled exception in (KERNEL32.DLL):0xE06D7363:Microsoft C++ Exce vc and access insert 记录

insert 后退出m_AdoConn.ExitConnect();数据库,界面关闭时报错:  Unhandled exception in (KERNEL32.DLL):0xE06D7363:Mi...
  • wyx100
  • wyx100
  • 2012年09月12日 15:21
  • 2169

大数据时代的数学思维(2)-混沌产生随机数

逻辑斯蒂映射的形式为 x_(n+1)=ax_n(1-x_n), 其中a是参数,当a>=3.569946时,x的值不再振荡,进入混沌,在此之前,x的值处于稳定状态,a值较小时,稳定在某个固定值,较大...
  • u010255642
  • u010255642
  • 2013年08月29日 10:52
  • 1659

混沌与非线性思维 课程感悟

内容概述 总体来看,课程讲了”非线性、虫口模型中的混沌、混沌概念及其演化、分形与混沌、分岔与混沌“这几个主要部分。 非线性章节分析了线性模型的意义,同时将线性思维与非线性思维进行对比,揭示两者的本...
  • u014135091
  • u014135091
  • 2014年06月21日 11:21
  • 898

Unhandled exception in al.exe(KERNELBASE.DLL):0xE06D7363:Microsoft C++Exception

问题描述: 出现Unhandled exception in al.exe(KERNELBASE.DLL):0xE06D7363:Microsoft C++Exception*****,对话框并出现...
  • wen417557721
  • wen417557721
  • 2016年07月11日 14:34
  • 1848
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:混沌 IN C++::Exception思维
举报原因:
原因补充:

(最多只允许输入30个字)