在堆栈内存上实例化一个类

huangapple go评论73阅读模式
英文:

Instantiating a class on Stack memory

问题

我可以帮你翻译以下内容:

我有以下类,我希望在堆栈内存上实例化它:

class ClassOnStack {
   int arr[];

public:
    
   ...
   // 一些方法
}

我有三个要求,其中两个是:

  1. 我希望在通过构造函数实例化它时指定arr的大小。
  2. 我想要完全在堆栈上实例化这个类。也就是说,数组'arr'也应该存储在堆栈上。

我想到的方法是使用模板并将new运算符设置为私有。

template<int ARRAY_LEN>
class ClassOnStack {

private:
  void *operator new(size_t size); // 重载并设置为私有                                                                                                                                               

public:
  int array[ARRAY_LEN];

  ClassOnStack() {
  }

  ....
  // 一些方法
};

但是这将要求我在头文件中定义方法,而我不想这样做。
第三个要求是:

  1. 我希望将实现保留在cpp文件中。

还有其他方法可以采取吗?

英文:

I have the following class which I wish to instantiate on stack memory:

class ClassOnStack {
   int arr[];

public:
    
   ...
   // somemethods();
}

I have three requirements, two of which are:

  1. I wish to specify the size of arr while instantiating it through a constructor.
  2. I want to instantiate this class entirely on stack. That is the array 'arr' should also be stored on stack.

The way I came up with is using templates and making new operator private.

template&lt;int ARRAY_LEN&gt;

class ClassOnStack {

private:
  void *operator new(size_t size); //overloaded and private                                                                                                                                               

public:
  int array[ARRAY_LEN];

  ClassOnStack() {
  }

  ....
  // somemethods()
};

However this will require me to define the methods within the header file which I don't wish to do.
The third requirement is:

  1. I wish to keep the implementation in the cpp file.

What are other approaches I can take ?

答案1

得分: 1

为满足您的第2和第3要求:

要将核心实现保留在.cpp文件中,并且仍然将模板类放在堆栈上,您可以考虑使用详细模式。

声明具有核心实现的类如下:

class ClassOnStackDetails {
private:
    int* _arr;
    size_t _arraySize;
public:
    ClassOnStackDetails(int* arr, size_t arraySize);
    void doSomething();
    int doSomethingElse();
};

然后,您的模板类,实际上在堆栈上实例化的类,可以在同一头文件中声明,或者在包含先前声明的另一个头文件中声明。模板类的构造函数只需将数组和其编译时大小作为指针传递给详细类。模板类的公共方法只需将不在头文件中的实现转发给详细类。

template<size_t ARRAY_LEN>
class ClassOnStack {

public:
    std::array<int, ARRAY_LEN> arr;

    ClassOnStack() : arr(), _details(arr.data(), arr.size()) {
        
    }

    void doSomething() {
        _details.doSomething();
    }

    int doSomethingElse() {
        return _details.doSomethingElse();
    }

private:
    ClassOnStackDetails _details;

};

请注意,我明确在arr之后声明了_details。如果您的实际工作变得更加复杂,可以在详细类中添加一个显式的init函数,该函数由模板类的构造函数调用。

然后,您的.cpp文件包含了ClassOnStackDetails的实现:

#include "ClassOnStack.h"

ClassOnStackDetails::ClassOnStackDetails(int* arr, size_t arraySize) :
_arr(arr),
_arraySize(arraySize) {
   // 进一步的初始化
}

void ClassOnStackDetails::doSomething() {
   // 您的代码在这里
}

int ClassOnStackDetails::doSomethingElse() {
   // 您的代码在这里
}

然后,在代码中,您可以简单地说:

int foo() {
    ClassOnStack<52> deckOfCards;
}
英文:

To satisfy your number 2 and 3 requirements:

To keep the core implementation in the .cpp file and still be a template class on the stack, you could probably use the details pattern.

Declare your class that has the core implementation like this:

class ClassOnStackDetails {
private:
    int* _arr;
    size_t _arraySize;
public:
    ClassOnStackDetails(int* arr, size_t arraySize);
    void doSomething();
    int doSomethingElse();
};

Then your template class, the one that actually gets instantiated on the stack, can be declared in the same header file or in another that #includes the previous declaration. The template class constructor just passes the array and its compile time size to the details class as a pointer. The public methods of the template class just forward to the details class where the implementation is not in the header file.

template &lt;size_t ARRAY_LEN&gt;
class ClassOnStack {

public:
    std::array&lt;int, ARRAY_LEN&gt; arr;

    ClassOnStack() : arr(), _details(arr.data(), arr.size()) {
        
    }

    void doSomething() {
        _details.doSomething();
    }

    int doSomethingElse() {
        return _details.doSomethingElse();
    }

private:
    ClassOnStackDetails _details;

};

Take note that I explicitly declared _details after arr. If your real work gets more complicated, you can add an explicit init function to the details class that gets called by the template class constuctor.

Then your .cpp file has the implementation for ClassOnStackDetails:

#include &quot;ClassOnStack.h&quot;

ClassOnStackDetails::ClassOnStackDetails(int* arr, size_t arraySize) :
_arr(arr),
_arraySize(arraySize) {
   // additional intitialization
}


ClassOnStackDetails::doSomething() {
   // your code goes here
}

int ClassOnStackDetails::doSomethingElse() {
   // your code goes here
}

Then in code, you can simply say:

int foo() {
    ClassOnStack&lt;52&gt; deckOfCards;
}

答案2

得分: 0

以下是翻译好的部分:

"Something like this works without any use of heap memory, with alloca(3):" -> "类似这样的方法可以在不使用堆内存的情况下工作,使用alloca(3):"

"Use it like this:" -> "使用方法如下:"

"Unfortunately it's too easy to use it incorrectly, e.g. if the user accidentally calls the constructor directly, and then forgets to destroy the data buf_ points to. It's possible to make that harder, but it's not possible to get rid of the macro." -> "不幸的是,如果用户意外地直接调用构造函数,然后忘记销毁buf_指向的数据,就会很容易使用不正确。可以让这变得更加困难,但无法摆脱这个宏。"

英文:

Something like this works without any use of heap memory, with alloca(3):

#include &lt;alloca.h&gt;
#include &lt;stddef.h&gt;
class ClassOnStack {
 public:
  ClassOnStack(size_t size, int *buf): size_(size), buf_(buf) {}
  // ...
 private:
  // ...
  size_t size_;
  int *buf_;
};
#define ALLOCA_SIZE_AND_BUF(size) (size), alloca(size)

Use it like this:

ClassOnStack cs(ALLOCA_SIZE_AND_BUF(size));

Unfortunately it's too easy to use it incorrectly, e.g. if the user accidentally calls the constructor directly, and the forgets to destroy the data buf_ points to. It's possible to make that harder, but it's not possible to get rid of the macro.

huangapple
  • 本文由 发表于 2023年8月5日 01:26:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76838036.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定