C ++中的golang样式“延迟”

我正在阅读 go 语言的defer语句。它允许您指定在函数结束时要采取的操作。例如,如果您有一个文件指针或资源,则无需使用每个可能的返回路径编写 free/delete,您只需指定一次 defer 函数。


看起来类似的东西最终可能会出现在 C++ 中(C++中的标准延迟/终结器实现是什么?,是否会有范围保护/范围退出习惯用法的标准化?)在此之前,使用具有析构函数进行回调?看起来局部变量的析构函数顺序是合理的,它也能很好地处理异常,尽管可能不会在信号上退出。


这是一个示例实现......有什么问题吗?


#include <iostream>

#include <functional>

using namespace std;


class FrameExitTask {

    std::function<void()> func_;

public:

    FrameExitTask(std::function<void()> func) :

    func_(func) {

    }

    ~FrameExitTask() {

        func_();

    }

    FrameExitTask& operator=(const FrameExitTask&) = delete;

    FrameExitTask(const FrameExitTask&) = delete;

};


int main() {

    FrameExitTask outer_task([](){cout << "world!";});

    FrameExitTask inner_task([](){cout << "Hello, ";});

    if (1+1 == 2)

        return -1;

    FrameExitTask skipped_task([](){cout << "Blam";});

}

输出: Hello, world!


烙印99
浏览 221回答 3
3回答

呼唤远方

Boost 在 Smart Pointer Programming Techniques 中对此进行了讨论:http://www.boost.org/doc/libs/1_59_0/libs/smart_ptr/sp_techniques.html#handle你可以这样做,例如:#include <memory>#include <iostream>#include <functional>using namespace std;using defer = shared_ptr<void>;&nbsp; &nbsp;&nbsp;int main() {&nbsp; &nbsp; defer _(nullptr, bind([]{ cout << ", World!"; }));&nbsp; &nbsp; cout << "Hello";}或者,没有bind:#include <memory>#include <iostream>using namespace std;using defer = shared_ptr<void>;&nbsp; &nbsp;&nbsp;int main() {&nbsp; &nbsp; defer _(nullptr, [](...){ cout << ", World!"; });&nbsp; &nbsp; cout << "Hello";}

暮色呼如

这已经存在,它被称为范围保护。看到这个精彩的演讲:https&nbsp;:&nbsp;//channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012-Andrei-Alexandrescu-Systematic-Error-Handling-in-C。这使您可以轻松创建要在退出时调用的任意可调用对象。这是较新的版本;它最初是在 go 出现之前很久就被开发出来的。它在一般情况下完美运行,但我不确定你所说的处理异常是什么意思。从必须在作用域退出时调用的函数抛出异常是一团糟。原因:当抛出异常(而不是立即捕获)时,当前作用域退出。所有析构函数都会运行,异常将继续传播。如果其中一个析构函数抛出异常,你会怎么做?您现在有两个实时异常。我想有一种语言可以尝试处理这个问题,但它非常复杂。在 C++ 中,抛出析构函数被认为是一个好主意是非常罕见的。

有只小跳蛙

这在 C++ 中已经存在,这是一个非常糟糕的主意,你给出的例子说明了为什么这是一件毫无意义的事情,我希望委员会永远不会引入它。例如,如果您有一个文件句柄,然后编写一个类来为您完成它,然后您就不必为每个用例编写 defer 语句,而您很容易忘记这样做。或者只是简单地弄错了。你写一个析构函数,一次。就是这样。然后,您可以保证该类的所有用途都是安全的。它更安全,更容易。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go