不确定的函数参数核算

来源:互联网 发布:金石软件视频 编辑:程序博客网 时间:2024/06/11 21:58

不确定的函数参数核算

    考虑如下函数:

         int  func(int x,int y);

    这个函数十分简单,它接受两个整型实参,并返回一个整型数,如果这样调用的话:

        int f1();

        int f2();

        func(f1(),f2());      //调用func,但实参为两个函数的返回值

    那么,问题在于func函数的参数进行核算的时候,是先调用f1还是先调用f2呢?答案可能很让你失望,因为在C++中,这个顺序是不确定的!

    可能,你会很疑惑,这个函数的正确运行与否跟核算的顺序有什么联系呢?即使在不确定顺序的情况下,我们的调用不是一样正确么?是的,对于这个函数而言

确实是这样,即使顺序不确定仍然可以得到正确的结果,但事实上不会总是那么幸运。

    考虑下面这个函数:

       int priority();

       class Widget{};

        void func(tr1::shared_ptr<Widget> p,int x);

    如果我们这样调用func的话

        func(tr1::shared_ptr<Widger>(new Widget),priority());

    那么调用次序可能:

        (1)调用new操作分配空间

        (2)调用Widget构造函数

        (3)调用priority函数

   当然,也有可能是这种情况:

       (1)调用new操作分配空间

       (2)调用priority函数

       (3)调用Widget构造函数

   那么,问题就在于针对这种情况,如果prority函数抛出一个异常,但已经调用了new操作分配空间,但却无法构造一个Widget对象,因为由于异常的存在导致Widget的构造函数没有调用,这就造成了我们很熟知的“内存泄露”。

       解决的方法其实很简单,产生这个问题的原因就在于我们把构造智能指针放到了函数内部,而由于函数参数核算顺序的不确定,从而可能导致内存泄露。既然如此,我们就把构造部分拿出函数参数,那么上述所存在的问题也就得到了很好的解决:

          tr1::shared_ptr<Widget> p(new Widget);

          func(p,priority());

      这样,就将调用new操作与调用Widget构造函数“绑定”在一起,即使priority函数产生异常,也不会影响到Widget对象的构造。