在 C++ 中返回时触发事件

Trigger event on return in C++

提问人:Luchian Grigore 提问时间:7/29/2011 更新时间:7/29/2011 访问量:1858

问:

我想在返回另一个函数之前执行某个函数。问题是有多个返回,我不想在每个返回之前复制粘贴我的调用。有没有更优雅的方法?

void f()
{
    //do something
    if ( blabla )
        return;
    //do something else
    return;
    //bla bla
}

我想在函数返回之前调用 g()。

C++语言

评论

0赞 Kerrek SB 7/29/2011
编写调度程序:void call_f() { f(); g(); }

答:

12赞 Andrey Agibalov 7/29/2011 #1
struct DoSomethingOnReturn {
  ~DoSomethingOnReturn() {
    std::cout << "just before return" << std::endl;
  }
};
...
void func() {
  DoSomethingOnReturn a;
  if(1 > 2) return;      
}

评论

0赞 Lea Hayes 7/29/2011
@loki2302不错的伎俩,但对我来说似乎有点矫枉过正......我只是将任何复杂性包装在一个简单的函数调用中,并将其返回给语法糖
1赞 Andrey Agibalov 7/29/2011
@Lea Hayes:为什么?简单而惯用的解决方案。
0赞 Lea Hayes 7/29/2011
@loki2302,由于展开堆栈并调用析构函数,将会产生更多的开销(取决于优化器的好坏)。显式调用一个简单的函数,因此理论上它应该更有效。你可以避免定义结构/类,因为一个简单的函数就可以解决问题。只是我个人的喜好。
1赞 KillianDS 7/29/2011
@Lea:肉体过早优化......。对于现代编译器来说,这很可能不会有什么区别(RAII很重要,不要优化它)
0赞 Andrey Agibalov 7/29/2011
@Lea Hayes:嗯,理论上编译器可以做任何它想做的事,而语义是一样的。
0赞 Lea Hayes 7/29/2011 #2
int g() {
    // blah
    return 0;
}

void f() {
    // do something
    if (blabla)
        return g();
    // do something else
    return g();
}

评论

0赞 Lea Hayes 7/29/2011
@Luchian对不起,我误读了你的问题,我已经更新了我的答案
2赞 laurent 7/29/2011 #3

对于这种事情,你可以简单地使用布尔值。这样你就没有太多的if/else语句了:

void f()
{
    //do something
    done = false;
    if ( blabla )
        done = true;
    //do something else

    if (!done) {
        // some code
        done = true;
    }

    if (!done) {
        // some other code
        done = true;
    }

    return;
}
2赞 2 revsravenspoint #4
void f()
{
    //do something
    if ( blabla )
        return;
    //do something else
    return;
    //bla bla
}

void f_callg()
{
    f();
    g();
}

如果无法访问从中调用 f() 的位置

void f_copy_of_old()
{
    //do something
    if ( blabla )
        return;
    //do something else
    return;
    //bla bla
}

void f()
{
f_copy_of_old();
g();
}
7赞 mkaes 7/29/2011 #5

有一些方法可以做到这一点。
一种是使用 boost::scope_exit 或使用结构并在析构函数中完成工作。
我不喜欢 boost 的预处理器语法,而且我懒得编写结构,所以我更喜欢使用 boost::shared_ptr 或在较新的编译器上使用 std::shared_ptr。喜欢这个:

std::shared_ptr<void>(nullptr, [](void*){ /* do your stuff here*/ });

评论

0赞 Evan Teran 7/29/2011
+1,不错!事实上,我认为 Boost 应该有一个在 C++0x 编译器上利用这一点的 scope_exit 版本!
4赞 Mark B 7/29/2011 #6

这通常表明,与其在每次返回之前尝试人为地执行某些操作,不如尝试将函数重构为单退出形式。然后做你的额外步骤是超级容易的,因为......只有一次回报。

评论

0赞 mmmmmm 8/3/2012
如果抛出异常,会发生什么情况?
4赞 Ragesh Chakkadath 7/29/2011 #7

我认为 try-finally 语句会做你想做的事。

void f()
{
    __try
    {
       //do something
       if ( blabla )
           return;
       //do something else
       return;
      //bla bla
    }
    __finally
   {
      g();
   }
}

try-finally 语句是 Microsoft 对 C 和 C++ 的扩展 使目标应用程序能够保证执行的语言 当代码块的执行中断时清理代码。清理 由取消分配内存、关闭文件和 释放文件句柄。try-finally 语句特别有用 对于具有多个位置的例程,可以对 可能导致例程过早返回的错误。

引自msdn。

评论

0赞 Andrey Agibalov 8/11/2011
它不是 C++,而是特定于 Microsoft 的扩展。
0赞 Ragesh Chakkadath 8/12/2011
在我的回答中已经提到过。它是 Microsoft 对 C 和 C++ 的扩展。但我不认为使用扩展会使它成为非 C++。
3赞 husky76 7/29/2011 #8
#define RETURN_IT g(); \
        return;

void f()
{
    //do something
    if ( blabla )
        RETURN_IT;
    //do something else
    RETURN_IT;
    //bla bla
}

很简单,虽然我有点喜欢洛基的建议