簡體   English   中英

為什么析構函數不接受C ++中的參數?

[英]Why destructors does not accept parameters in C++?

最近,我遇到了一個例子,我的析構函數需要使用一個參數。

我正在研究一個C包,該包在內部管理內存,並使用其自身的參數跟蹤分配和釋放。 我不想破壞這一點。

我編寫了C代碼,該代碼初始化了自己的數據結構並在最后釋放了它們。 當我決定遷移到C ++時,我意識到分配數據結構和釋放數據結構應該放在構造函數和析構函數中。 因此,我將這些函數更改為構造函數和析構函數。 我現在的問題是我需要使用一個參數傳遞給析構函數以釋放分配的數據。 該參數不在我自己的代碼中,而是C,我不想弄亂它。

我的問題是雙重的:

為什么C ++首先決定不接受析構函數中的參數? 和我有什么選擇? (我可以保存指向該參數的指針,或在析構函數中以某種方式調用該函數,但這似乎不是C ++編程的好習慣)

更新:添加一些代碼這是我的虛構類:

class paru_symbolic/* paru_symbolic*/
{
    public:
        paru_symbolic ( cholmod_sparse *A, cholmod_common *cc ); // constructor
        ~paru_symbolic (cholmod_common *cc ); // destructor

        // -------------------------------------------------------------------------
        // row-form of the input matrix and its permutations
        // -----------------------------------------------------------------------
              //--- other stuff
                     ...
};

這是我當前的C構造函數:

#include "Parallel_LU.hpp"
paru_symbolic *paru_sym_analyse
(
 // inputs, not modified
   cholmod_sparse *A,
 // workspace and parameters
   cholmod_common *cc ){   

    DEBUGLEVEL(0);
...
   aParent = (Int*) paru_alloc (m+nf, sizeof(Int),cc);

...
}

和析構函數:

void paru_freesym (paru_symbolic **LUsym_handle,
            // workspace and parameters
    cholmod_common *cc
){
    DEBUGLEVEL (0);
    if (LUsym_handle == NULL || *LUsym_handle == NULL){
        // nothing to do; caller probably ran out of memory
        return;
    }

    paru_symbolic *LUsym;
    LUsym = *LUsym_handle;

    Int m, n, anz, nf, rjsize; 
...
    cholmod_l_free (m+nf, sizeof (Int), LUsym->aParent, cc);

...
    cholmod_l_free (1, sizeof (paru_symbolic), LUsym, cc);

   *LUsym_handle = NULL;
}

參數cc用於SuiteSparse軟件包中,以跟蹤分配和釋放數據。 它已在SuiteSparse軟件包中廣泛使用,是跟蹤內存的有用工具。 有人提到誰想要將參數傳遞給析構函數,這很公平,但是我們可以擁有與構造函數相同的默認參數。

析構函數中的參數沒有意義,因為當對象超出范圍時會自動調用析構函數。 您如何向該參數傳遞參數?

{ 
   Foo x;
} // `~Foo()` is automatically called here

您可能想要的是將資源存儲在您的課程中。 這是一個帶有動態分配指針的不現實示例:

struct RAIIPointer
{
    Foo* ptr;

    // Initialize the resource
    RAIIPointer() : ptr{new Foo{/*...*/}}
    {
    }

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

    RAIIPointer(RAIIPointer&&) { /* implement appropriately */ }
    RAIIPointer& operator=(RAIIPointer&&) { /* implement appropriately */ }

    // Release the resource
    ~RAIIPointer() 
    {
        delete ptr;
    }
};

請注意,在實際情況下,您將使用std::unique_ptr ,並且如果您要實現自己的RAII資源類,則需要實現正確的復制/移動操作。

@Vittorio的答案是通用的方法。 我將根據您添加的示例代碼對其進行定制。

您提出問題的方式如下:

  1. 您可以使用實用程序類型cholmod_common對您的類型進行一些有用的工作。
  2. 該類型的實例可以傳遞給您創建的幾個paru_symbolic對象。
  3. 沒有一個paru_symbolic實例擁有它的唯一性,但是它們在生命周期的開始和結束時都依賴於它。 它必須與所有這些對象存在相同的持續時間。

那對我尖叫std::shared_ptr

class paru_symbolic
{
    std::shared_ptr<cholmod_common> _cc;
    public:
        paru_symbolic ( cholmod_sparse *A, std::shared_ptr<cholmod_common> cc)
         : _cc(cc) {
           // constructor
         } 
        ~paru_symbolic () {
          // use _cc , it's guaranteed to live until the closing brace at the least.
        }
};

而已。 所有權現已共享。 依賴cholmod_common實例的最后一個對象將是不需要您做任何額外工作即可清除它的對象。

在C ++中,這種事情是通過分配器完成的,另請參見std::allocator 因此,您可以使用cholmod_common*數據成員創建自己的分配器。

另外,您可以使用deleter參數通過智能指針進行內存管理。 例如

class foo
{
  struct bar_deleter {
    cholmod_common *cc;
    bar_deleter(cholmod_common *c) : cc(c) {}
    void destroy(bar*) { cc->free(bar); }
  };
  std::unique_ptr<bar,bar_deleter> data;
public:
  foo(some_type const&input, cholmod_common *cc)
    : data(cc->create<bar>(input), bar_deleter(cc)) {}
};

當然,它也與數據保持cholmod_common*

名稱“ cholmod_common ”表明這是一種公共資源,即在任何給定時間只有一個cholmod_common對象。 當且僅當是這樣的話,那么你可以使用一個無狀態的分配,這使公共資源作為一個靜態數據成員(或通過其獲取 )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM