【问题标题】:c++ self-defined placement new and placement delete invokingc++自定义placement new和placement delete调用
【发布时间】:2023-03-22 11:29:01
【问题描述】:

我想定义我自己的展示位置 new 和展示位置删除(采用额外参数),我发现我可以正确调用展示位置,而我无法访问展示位置删除。谁能告诉我是我错误地定义了展示位置删除还是我错误地调用了它?

class A
{
public:
    A( int a ) : a(a){}

    static void* operator new( std::size_t, int ); // the placement new
    static void operator delete( void*, int )throw(); // the corresponding placement delete
private:
    int a;
};

void* A::operator new( std::size_t size, int n )
{
    std::cout << "size: " << size << "  " << "n: " << n << std::endl;
    return ::operator new(size);
}

void A::operator delete( void* p, int n )throw()
{
    std::cout << "n: " << n << std::endl;
    ::operator delete(p);
}

int main( int argc, char* argv[] )
{
    A* a = new(10) A(100);

    std::cout << std::endl;

    delete(4) a; // error???????????????????, but how?

    return 0;
}

【问题讨论】:

  • 这看起来不像是新放置,尤其是您实例化 A * 指针的方式(不确定 10 是否是正确的内存位置:P)。看这里:parashift.com/c++-faq/placement-new.html
  • @Xaqq:它是一种的放置新形式,但不是最常见的一种,它传递对象将被放置的地址。
  • 我宁愿单独留下new和delete,而是定义适当的构造函数/析构函数——即使它有效,但它没有,如果A * a = new A的行为与A a
  • 在你的类A的构造函数中,构造函数的参数a与成员变量同名:a。永远不要陷入将参数命名为与成员变量相同的陷阱。如果你对你的编译器撒谎,它可能会相信你。

标签: c++ placement-new placement


【解决方案1】:

Placement delete 仅可用于处理在评估 Placement new 表达式期间发生的异常。如果构造成功完成,那么稍后将使用正常的delete。

您可以显式调用放置解除分配函数,但它的行为与delete 运算符不同(它不会自动调用析构函数)。

在你的情况下,相应的代码是:

a->~A();
A::operator delete(a, 4);

糟糕!

对于数组,情况更糟,因为您无法从编译器存储它以供自己使用的位置检索元素的数量(以及要调用的析构函数的数量)。

设计您的重载operator new,使其与单参数operator delete 正确配对。然后您班级的用户可以使用delete ptr; 和std::unique_ptr 等。

如果您确实需要自定义解除分配,那么使用自定义删除器返回 std::shared_ptr 的分配包装器将比自定义放置新的更好。

【讨论】:

  • 这是否意味着我不能更改placement delete的签名,我只能重新定义它?而当我想释放资源时,我调用:a->~A();删除一个; ?
  • @JavaBeta:不会。delete a; 会第二次调用析构函数,然后调用单参数释放函数operator delete(void*)。如果您想调用不同的(放置)释放函数,请像我的答案所示明确地这样做。如果您可以使普通的释放函数正常工作,那么您的类的用户可以只说delete p; 并立即获得析构函数调用和释放。
  • 哦,我必须通过作用域运算符显式调用它?它有效,它仍然让我感到困惑,无论如何放置新和放置删除调用机制非常不一致。
  • @JavaBeta:这是因为您不打算使用展示位置删除。它在那里,您可以使用它,但出于技术原因(请参阅stackoverflow.com/a/14119344/103167 也在 cmets 中链接到此问题)它不是无缝的。
  • 是的,我想我再次混淆了 operator delete 和 delete 表达式。感谢您的@Ben Voigt 即时和乐于助人的 cmets!
猜你喜欢
  • 2021-08-31
  • 1970-01-01
  • 2021-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-26
  • 2017-10-12
相关资源
最近更新 更多