編輯:討論了這個答案多一點(與查爾斯貝利),我認爲這是不安全的,因爲它取決於實施boost :: function。
當我們進入actual_foo會是這個樣子的調用堆棧:
actual_foo
boost::function::operator()
main
所以當actual_foo執行完畢,我們會跳回的boost::function
的operator()
代碼,這個對象已被刪除。這不能保證是一個問題 - 這有點像調用delete this
- 但你必須非常小心你在刪除對象的成員函數中所做的事情。您不允許調用任何虛擬功能或使用任何數據成員。
問題是,我不知道boost::function
對它在調用函數後調用operator()
時做了什麼保證。在我的平臺上它似乎沒有做任何危險的事情(所以valgrind沒有抱怨),但完全可以想象,在不同的平臺,不同的實現,或不同的編譯標誌,它可能想做的事情是不是一旦對象被刪除就不允許 - 例如,它可能使用成員變量寫出一些調試信息。
因此,我認爲這是做可能會導致在某些情況下不確定的行爲很危險的事。
進一步注:
我參加了一個快速瀏覽一下升壓真的做得它調用函數指針之後。在這裏尋找:http://boost.cvs.sourceforge.net/viewvc/boost/boost/boost/function/function_template.hpp?view=markup在687行的operator()函數中,我的解釋是它立即返回返回值,並且什麼也不做,所以在實踐中,通過這個實現,你應該沒問題,但是關於它的評論危險仍然存在。請注意,我很可能已經發現的代碼錯誤位和/或理解錯了......
原文如下答案:
我相信這是好的。通過輸入actual_foo
時,boost::bind
和boost::function
對象已經完成了自己的工作,而你正在執行的實際功能actual_foo
。
我在我的平臺(gcc 4.2.4,Linux)上通過運行程序valgrind檢查了這一點。
這裏是我跑的程序:
#include <boost/bind.hpp>
#include <boost/function.hpp>
class Magic
{
public:
int magic(int i)
{
return 5;
}
};
typedef boost::function<int(int)> foo_type;
foo_type* global_foo = NULL;
int actual_foo(int i, Magic* m)
{
delete global_foo;
return m->magic(i);
}
int main()
{
Magic m;
global_foo = new foo_type(boost::bind(&actual_foo, _1, &m));
return (*global_foo)(10);
}
這裏是Valgrind的輸出:
$ valgrind ./boost_bind
==17606== Memcheck, a memory error detector.
==17606== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==17606== Using LibVEX rev 1804, a library for dynamic binary translation.
==17606== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==17606== Using valgrind-3.3.0-Debian, a dynamic binary instrumentation framework.
==17606== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==17606== For more details, rerun with: -v
==17606==
==17606==
==17606== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 17 from 1)
==17606== malloc/free: in use at exit: 0 bytes in 0 blocks.
==17606== malloc/free: 1 allocs, 1 frees, 16 bytes allocated.
==17606== For counts of detected errors, rerun with: -v
==17606== All heap blocks were freed -- no leaks are possible.
我必須說,雖然,這似乎是一個奇怪的事情。如果可能的話,我更願意使用自動刪除此函數對象,方法是將其設置爲堆棧變量,或者在堆棧變量的析構函數中將其刪除(如RAII)。它會更整潔,更安全,不那麼可怕,並且更加安全。但我相信你已經知道了這一切,並且有充分的理由與代碼一起生活。
總結,它可能是危險的,這取決於operator()調用在實現中做了什麼。你不能保證它的功能,所以假設它很危險。 boost :: function的當前實現將是安全的。 – 2009-08-14 16:35:00