2014-02-08 68 views
8

我有一個類與刪除副本ctor和釋放C資源的析構函數。爲什麼emplace_back調用析構函數?

我希望emplace_back只移動一次對象並調用析構函數一次,但它在emplace_back中被調用,如下面的linux中的stl實現中所見。這是爲什麼發生?

結果是C資源被釋放多次。

statement(statement&&) = default;             
    statement& operator=(statement&&) = default;          

    private:                   
    statement(const statement&) = delete;            
    statement& operator=(const statement&) = delete; 




396│ template<typename _Tp, typename _Alloc> 
397│  template<typename... _Args> 
398│  void 
399│  vector<_Tp, _Alloc>:: 
400│  _M_emplace_back_aux(_Args&&... __args) 
401│  { 
402│   const size_type __len = 
403│   _M_check_len(size_type(1), "vector::_M_emplace_back_aux"); 
404│   pointer __new_start(this->_M_allocate(__len)); 
405│   pointer __new_finish(__new_start); 
406│   __try 
407│   { 
408│    _Alloc_traits::construct(this->_M_impl, __new_start + size(), 
409│          std::forward<_Args>(__args)...); 
410│    __new_finish = 0; 
411│ 
412│    __new_finish 
413│    = std::__uninitialized_move_if_noexcept_a 
414│    (this->_M_impl._M_start, this->_M_impl._M_finish, 
415│    __new_start, _M_get_Tp_allocator()); 
416│ 
417│    ++__new_finish; 
418│   } 
419│   __catch(...) 
420│   { 
421│    if (!__new_finish) 
422│    _Alloc_traits::destroy(this->_M_impl, __new_start + size()); 
423│    else 
424│    std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator()); 
425│    _M_deallocate(__new_start, __len); 
426│    __throw_exception_again; 
427│   } 
428├>  std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, 
429│      _M_get_Tp_allocator()); 
430│   _M_deallocate(this->_M_impl._M_start, 
431│      this->_M_impl._M_end_of_storage 
432│      - this->_M_impl._M_start); 
433│   this->_M_impl._M_start = __new_start; 
434│   this->_M_impl._M_finish = __new_finish; 
+0

此答案與我的問題相關: http://stackoverflow.com/a/12739939/72784 – piotr

+1

如果您在移動ctor上添加一些'noexcept',該怎麼辦?這會有幫助嗎? – detunized

+0

這看起來像'矢量'的調整大小函數,即它分配一個新緩衝區,將元素從舊緩衝區複製/移動到新緩衝區,並銷燬舊緩衝區中的元素(但不在新緩衝區中)。確保你的移動構造函數正確*傳輸*資源,並使用新資源或沒有任何資源離開移動的對象,以便它可以在不影響移動到的對象的情況下被銷燬。 – dyp

回答

4

有跡象表明,已經逃脫你的通知,兩件事情:

  1. A移動,從對象仍然會遭到破壞,所以你的移動操作必須轉移資源
  2. vector增長,它可能需要重新分配這是一個4步操作:獲取新存儲,移動構建(或複製構建)新存儲中的新元素(從舊存儲),銷燬舊元素,釋放舊存儲。

所以,你的問題只是你不正確地轉移資源;使用std::unique_ptr作爲您的自定義類的基礎,你不會遭受這樣的災難。

+0

我通過顯式地在移動構造函數上傳遞資源來修復它,所以在這種情況下析構函數不會釋放它。 – piotr

相關問題