c++ 检查内存是否在堆上?[副本]

p3rjfoxz  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(126)

此问题已在此处有答案

How to know if a pointer points to the heap or the stack?(14个回答)
六年前就关门了。
我有一个类,它的constructor将对象的地址作为参数。

MyClass(OtherClass * otherClass);

在这个类的Destructor中,我尝试deleteOtherClass的示例。

~MyClass() {
    if(otherClass != nullptr) {
        delete otherClass;
    }
}

我遇到的问题是,当我调用这个constructor时,我使用来自stack的元素而不是来自heap的元素来调用它,因此我将其调用如下:

MyClass myClass(&otherObject);

所以当myClass对象超出作用域时,我会得到一个异常。我如何知道我的OtherObject变量是在stack还是heap上声明的?或者换句话说,我怎么知道我是否能delete对象?

kmbjn2e3

kmbjn2e31#

虽然有一些特定于系统的方法可能能够区分内存是来自堆还是来自堆栈,但这实际上并没有真正帮助:你可能得到了一个指向堆上另一个对象的成员的指针。内存会在堆上,但你仍然不负责删除对象。换句话说:不要走你现在走的路!
处理这个问题的正确方法是在接口中明确所有权语义,并与之配合。基本上有两个方向,你可以采取:
1.你的类可以故意接管在构造函数中传递的指针的责任!相反,你的类的用户有责任处理这些对象 * 和 *,以保证它们在你的对象存在时是有效的。如果你可以得到指向栈(或成员)对象的指针,那么用户已经必须保证这些对象的有效性,而对于其他方式来说,user 处理它们可能完全是微不足道的,例如,通过std::unique_ptr<OtherClass>管理它们。
1.你的类负责传递的所有对象,它将delete所有对象。调用者的责任是 * 不 * 将指针传递到其他地方管理的对象,例如,堆栈上的对象或成员对象。
有一种混合的方法,你的类有时负责对象,但不总是这样。然而,这种方法的实现实际上是上述两种方法的组合:你会把一个合适的智能指针作为构造函数的参数,用户有责任确保智能指针是由你的类的用户正确地构造的。例如,你的类可以接受一个std::shared_ptr<OtherClass>,对于它,正常的构造将delete对象。当用户想要传入一个指向其他所有对象的指针时,std::shared_ptr<OtherClass>将用一个删除器来构造,该删除器不 * delete指针。下面是一个简单的程序,演示了std::shared_ptr的两种不同管理策略:

#include <iostream>
#include <memory>

struct foo {
    char const* name;
    foo(char const* name)
        : name(name) {
        std::cout << "foo::foo(" << name << "): " << this << "\n";
    }
    ~foo() {
        std::cout << "foo::~foo(" << name << "): " << this << "\n";
    }
};

int main() {
    std::shared_ptr<foo>(new foo("heap"));
    foo f("stack");
    std::shared_ptr<foo>(&f, [](auto){});
}

相关问题