检查内存是否在堆上?

Arc*_*ede 2 c++ memory-management

我有一个类,constructor它将对象的地址作为参数.

MyClass(OtherClass * otherClass);
Run Code Online (Sandbox Code Playgroud)

Destructor这个类中,我尝试delete了实例OtherClass.

~MyClass() {
    if(otherClass != nullptr) {
        delete otherClass;
    }
}
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是,当我调用constructor它时,我用一个元素来stack代替heap它来调用它,因此我将其称为如下:

MyClass myClass(&otherObject);

所以当myClass对象超出范围时,我得到一个例外.如果我的OtherObject变量是stackheap?或者?上声明的,我怎么能够喜欢?或者换句话说,我怎么知道我是否可以delete对象?

Die*_*ühl 6

虽然有一些系统特定的方法可能能够判断内存是来自堆还是来自堆栈,但这实际上并没有真正帮助:你可能有一个指向堆上另一个对象成员的指针.内存将在堆上,但您仍然不负责删除该对象.换句话说:不要下去你的路径!

处理问题的正确方法是在界面中明确地清楚所有权语义,然后继续使用.您可以采取以下两个方向:

  1. 你的类可以故意接管构造函数中传递的指针的责任!相反,类的用户有责任处理这些对象,保证它们在对象存在时有效.如果您可以获得指向堆栈(或成员)对象的指针,则用户已经必须保证这些对象的有效性,并且对于其他方式,用户处理它们可能完全是微不足道的,例如,通过管理它们std::unique_ptr<OtherClass>.
  2. 你的班负责传递的所有对象,它将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){});
}
Run Code Online (Sandbox Code Playgroud)