是否可以使用自定义分配运算符来创建STACK对象?

时间:2013-08-18 08:35:30

标签: c++

好的,如果我想用自定义新运算符创建堆对象,我知道我需要像这样重载new运算符:

void* operator new(size_t size, int unused)
{
    void* ptr = malloc(size);
    //some custom code
    return ptr;
}

然后,如果我想使用这个重载的运算符创建一个堆对象,我会这样做:

SomeClass* a = new(0) SomeClass;

问题是:我可以做这样的事情来创建堆栈对象吗?

2 个答案:

答案 0 :(得分:2)

我同意其他答案,你可能不需要这个,但你可以做到。请参阅下面的示例代码,只是提前分配内存并将其传递给placement new。如果您使用数组new []表单,可能需要执行此操作,您可能会执行类似

的操作

void * rawMemory = operator new [](25 * sizeof(std :: stack));

如果你有一个堆栈数组,你有一个管理资源或其他东西的工厂方法。无论哪种方式,它取决于您的应用程序和用例。下面是一个简单的例子

  #include <iostream>
#include <stack>

int main ( int argc, char *argv[])
{
  void *rawMemory = operator new(sizeof(std::stack<unsigned int>));
  std::stack<unsigned int> *s = new (rawMemory) std::stack<unsigned int>;

  s->push(10);

  std::cout << s->top() << std::endl;

  return 0;
}

使用阵列版本的第二个示例,在您管理25个不同堆栈并将其交给客户端时,这似乎更有用。另外,回答你的评论。看到容器这次是在堆栈定义中定义的,在这种情况下我使用了容器的向量。 Stack是一个容器,但它有一个底层容器,默认为deque

#include <iostream>
#include <stack>
#include <vector>

int main ( int argc, char *argv[])
{
  typedef std::stack<unsigned int,std::vector<unsigned int> > StackType;

  void *rawMemory = operator new[](25*sizeof(StackType));

  StackType *stacks = static_cast<StackType*> (rawMemory);

  // allocate
  for ( unsigned int i = 0; i < 25; ++i )
  {
    new (stacks+i) StackType;
  }

  stacks[1].push(10);
  std::cout << stacks[1].top() << std::endl;

  // don't forget to delete or smart resize
  for ( int i = 24; i >= 0; --i )
  {
    StackType x;
    std::swap ( x, stacks[i] );
  }

  return 0;
}

答案 1 :(得分:1)

您可以像这样定义一个宏:

#define STACK_NEW(T) new (alloca(sizeof(T))) T

使用 placement new alloca()在堆栈上分配块并在其上构造类型为T的对象。您还可以定义阵列版本:

#define STACK_NEW_ARRAY(T, n) new (alloca(n * sizeof(T))) T

您可以通过以下方式使用此宏:

int * p = STACK_NEW(int);
MyObj * q = STACK_NEW(MyObj) (my, constructor, parameters);
int * r = STACK_NEW_ARRAY(int, 42);

您将手动破坏这些对象:

q->~MyObj();

删除它们会有不确定的行为。

警告 :整个设施非常不安全。我强烈建议您不要在代码库中使用这种系统性危险的工具。据我所知,没有安全的方法可以使用它,让你感到痛苦!