如何重载 new 运算符以在堆栈上分配? [关闭]

Posted

技术标签:

【中文标题】如何重载 new 运算符以在堆栈上分配? [关闭]【英文标题】:How can I overload the new operator to allocate on the stack? [closed] 【发布时间】:2012-10-18 21:13:34 【问题描述】:

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

这样的事情怎么样:

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

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

上述解决方案是否有效?

【问题讨论】:

嗯,你不可能有堆栈和堆的原因。 如果用户不仅不必调用delete,而且也不必调用new,该怎么办?那不是更好吗? 我认为 avakar 确实在这里有所作为。你绝对应该走那条路=P @user965369:您的问题中没有关于私有构造函数的内容。我们可以在问题中提供您的实际用例吗? 整个想法没有意义,因为即使可以做到,也会违反new的“预期行为”——分配一个生命周期与当前无关的对象范围。哎呀,如果调用者想在堆栈上分配对象将在堆栈上分配它,句号! (s/在堆栈上/具有自动存储持续时间/) 【参考方案1】:

不要!

使用自动存储...

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?

另一种方法可能是 placement new,但这是一条黑暗且危险的旅行路线,我现阶段当然不建议这样做。或者,坦率地说,任何阶段......你通常仍然需要手动销毁。你得到的只是使用关键字new,这似乎毫无意义。

【讨论】:

+1:我喜欢大胖子不要! 只是添加一个链接:Why not use pointers for everything in C++? 和 Proper stack and heap usage in C++?【参考方案2】:

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

看看你实际上想要做什么,你说你认为这很棒的原因是:

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

该功能是使用smart pointers 实现的。我强烈建议您花时间学习这些内容。

【讨论】:

【参考方案3】:

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

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 返回正确对齐的内存 - 否则行为未定义。

【讨论】:

它已经在 C++ 中,它是“当你不需要它时不使用new”,特别是放置new。除非你真的需要它,否则避免放置 new ,特别是如果你以如此幼稚的方式使用它(不检查缓冲区的对齐方式)。 @MatteoItalia 为我的答案添加了正确的对齐方式。顺便说一句,OP 似乎需要它,否则为什么 OP 会发布这个问题? @PiotrNycz 因为他不知道自己想要什么或不了解危险? 如果你问我,似乎 OP 不知道他在问什么。如果这个问题的重点是“基本上这样用户就不必在之后调用 delete”,那么放置 new 不是一个解决方案,因为您必须手动调用析构函数。合乎逻辑的解决方案是调用者只需使用自动存储或智能指针分配对象。 @MatteoItalia - 是的 - 经过一番考虑,我将此作为第一个答案。但只是对于可能坚持实现这个“新堆栈”的下一个读者——我离开了下一部分——不需要实现已经实现的东西。【参考方案4】:

我认为这里的好答案是:

不要重载 operator new。

如果你想走那条路,可以看看this question。

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

【讨论】:

以上是关于如何重载 new 运算符以在堆栈上分配? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

重载 [] 和 = 运算符以在 C++ 中接受我的模板类的值

问题是在具有-02或以上优化的框架中重载运算符new和delete [关闭]

重载类的new和delete运算符成员函数

如何确定 Rust 中的 new() 何时在堆栈或堆上分配

c++ primer19.1.1重载new和delete

c++内存分配(new,operator new)详解