0

如何为类类型重载 new 运算符,以便它在堆栈而不是堆上分配内存(基本上这样用户就不必在之后调用 delete)。

像这样的东西怎么样:

class A{
    private:
        A(int i):
           this->i(i);
        {}
        A a;
        int i;

    public:
        void* operator new(size_t sz){
            a(12);
        }
};

上述解决方案有效吗?

4

4 回答 4

9

不!

使用自动存储...

new运算符旨在实现动态分配(您称之为“堆上”),尽管您可以提供自己的分配器,但您不能将其扭曲为遵守自动存储持续时间对象的范围规则(您是什么调用“在堆栈上”)。

相反,写:

MyType myobject;  // automatic storage duration

...或智能指针...

或者,如果您不介意动态存储持续时间,但只想避免以后手动销毁,请使用智能指针:

std::unique_ptr<MyType> myptr(new myobject());  // unique, dynamic storage duration
std::shared_ptr<MyType> myptr(new myobject());  // shared, dynamic storage duration

这两者都可以在 C++11 ( std::) 和 Boost ( boost::) 中找到。

...或安置new

另一种方法可能是安置新的,但这是一条黑暗而危险的旅行路径,我现阶段当然不推荐。或者,坦率地说,任何阶段......你通常仍然需要手动销毁。您所获得的只是使用关键字new,这似乎毫无意义。

于 2012-10-29T14:33:53.783 回答
2

我认为这里的好答案是:

不要重载 operator new。

如果你还想走那条路,可以看看这个问题

如果没有,您始终可以使用智能指针或共享指针来避免用户不得不删除分配的内存。

于 2012-10-29T14:35:39.020 回答
1

看来你不知道你在问什么。根据定义,new 运算符在堆上分配内存。要在堆栈上创建对象,只需将其声明为局部变量。

看看你真正想做的事情,你说你认为这很棒的原因是:

基本上这样用户就不必在之后调用 delete

并且该功能是使用智能指针实现的。我强烈建议你花时间学习这些。

于 2012-10-29T14:34:48.973 回答
1

为什么不只是自动变量(它是“在堆栈上”并且不需要手动调用析构函数:

int foo() {
  A a;
  int i;
  ...
  // don't need to call delete

}


从字面上回答你的问题,有一个新的位置,它从用户那里获取内存 - 所以你可以把这个内存作为自动缓冲区:

  alignas(int) char buffer[sizeof(int)];
  int* p = new (buffer) int;
  //           ^^^^^^^^

对于非 POD 对象 - 你不需要调用 delete - 但你必须手动调用析构函数:

  class A { public: ~A(){} };
  alignas(A) char buffer[sizeof(At)];
  A* p = new (buffer) A;
  //         ^^^^^^^^
  p->~A();

alignas在 C++11 中是新的——在 C++03 中,你必须以不同的方式处理正确的对齐。必须返回正确对齐的内存new- 否则行为未定义。

于 2012-10-29T14:35:16.983 回答