繁体   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