2015-09-17 75 views
0

在自定義轉換器中,我正在檢查序列項是否是某種類型。到目前爲止,我有這個代碼(簡體)使用boost :: python :: handle作爲臨時?

namespace bp=boost::python; 
/* ... */ 
static void* convertible(PyObject* seq_ptr){ 
    if(!PySequence_Check(seq_ptr)) return 0; 
    for(int i=0; i<PySequence_Size(seq_ptr); i++) 
     if(!bp::extract<double>(PySequence_GetItem(seq_ptr,i)).check()) return 0; 
    /* ... */ 
} 
/* ... */ 

但這泄漏內存,因爲PySequence_GetItem is returning a new reference。所以要麼我可以在循環中做這樣的事情:

PyObject* it=PySequence_GetItem(seq_ptr,i); 
bool ok(bp::extract<double>(it).check(); 
Py_DECREF(it); // will delete the object which had been newly created 
if(!ok) return 0; 

但這相當笨拙;我可以做一個獨立的功能,但我正在調用bp::handle實現計數器;所以這樣的事情可以做:

if(!bp::extract<double>(bp::handle<>(PySequence_GetItem(seq_ptr,i))).check()) return 0; 

但使用手柄作爲臨時工氣餒this page提到。爲什麼?在.check()實際被調用之前,對象是否可以被銷燬?有沒有其他優雅的方式來寫這個?

回答

1

在調用.check()之前,對象不會被銷燬,並且在發佈的上下文中是安全的。

不使用臨時對象的建議是由於對參數和異常安全性評估的未指定順序。如果只有一個可以評估參數的順序,比如在你的例子中,那麼它是安全的。例如,考慮功能bad()總是拋出一個異常:

f(boost::python::handle<>(PySequence_GetItem(...)), bad()); 

如果bad()PySequence_GetItem(...)boost::python::handle<>(...)之間的評估,然後在新的參考會被泄露的堆將開始boost::python::handle<>施工前放鬆。在另一方面,當非臨時使用,沒有機會爲某事PySequence_GetItem()boost::python::handle<>()之間扔了,所以下面是在異常的情況下安全:

boost::python::handle<> item_handle(PySequence_GetItem(...)); 
f(item_handle, bad()); 

考慮閱讀香草薩特的GotW #56: Exception-Safe Function Calls爲更多細節。

相關問題