我怎么知道指针是否已经通过' new'?

时间:2013-04-17 03:11:02

标签: c++ pointers new-operator delete-operator

说我有这样的指针:

int *thingy;

在某些时候,可能会或可能不会调用此代码:

thingy=new int;

我如何知道我是否可以这样做:

delete thingy;

我可以为每个指针使用bool,并在每次使用true时将bool标记为new,但是我有很多指针,这会非常笨拙。

如果我没有在new上拨打thingy,则在其上调用delete可能会导致崩溃,对吗?

我搜索了很多,但找不到明显符合我情况的答案。

编辑:我需要能够delete指向我喜欢的指针多次,而指针不一定指向任何数据。如果这是不可能的,我将不得不重新编写我的代码。

4 个答案:

答案 0 :(得分:4)

始终将其初始化为NULL

int *thingy = NULL;

然后

delete thingy;
thingy = NULL;
即使thingy为NULL,

也有效。您可以根据需要进行多次删除,只要thingy NULL delete没有不必要的副作用。

答案 1 :(得分:2)

没有内置的方法来判断特定指针值是否delete能够。相反,你只需要设计程序来做正确的事情,最好是根据你的要求仔细设计资源所有权政策,然后用RAII之类的方法来实现它们。

给定适当的RAII类型,您不需要在代码周围分散delete或其他资源管理命令。您只需初始化并使用相应类型的对象,并将对象本身保持清洁。例如,如果RAII类型unique_ptr对应于您要使用的所有权政策,那么您可以通过以下方式管理对象:

unique_ptr<int> thingy {new int};
// use thingy ...

无需手动清理,因为unique_ptr会为您处理。

另一方面,如果您尝试直接管理资源,最终会得到许多代码,例如:

int *thingy = nullptr;

// ...

thingy = new int;

try {
    // something that might throw
} catch(...) {
    delete thingy;
    thingy = nullptr;
    throw;
}

delete thingy;
thingy = nullptr;

答案 2 :(得分:0)

没有内置的C ++工具来识别指针是否指向堆数据并且可以安全地delete d。删除NULL指针是安全的,您可以将其数据已被删除的每个指针设置为NULL。但这无助于区分堆数据指针和指向其他数据或代码的指针。

当您的操作系统启动一个过程时,它会将代码和数据部分定位到特定的数据区域。在Windows中,这部分由EXE文件的PE头控制。因此,存储区域的实际地址可以变化。但是你可以确定这些地区的位置:

  • BSS
  • 数据

获取每个区域的地址范围后,您可以区分指向堆数据的指针(其中删除是合适的)和指向堆栈数据的指针。这允许您区分delete能力和必须不删除其指针的数据。

答案 3 :(得分:0)

编写一个为您进行跟踪的包装类,例如:

template<typename T>
class ptr_t
{
private:
    T* m_ptr;
    bool m_delete;

    ptr_t(const ptr_t&) {}
    ptr_t& operator=(const ptr_t&) { return *this; }

public:
    ptr_t()
        : m_ptr(NULL), m_delete(false)
    {
    }

    ptr_t(T *ptr, bool del)
         : m_ptr(ptr), m_delete(del)
    {
    }

    ~ptr_t()
    {
       reset();
    }

    void assign(T *ptr, bool del)
    {
        if (m_delete)
            delete m_ptr;
        m_ptr = ptr;
        m_delete = del;
    }

    void reset()
    {
        assign(NULL, false);
    }

    operator T*() { return m_ptr; }
    bool operator!() const { return (!m_ptr); }
};

typedef ptr_t<int> int_ptr;

int_ptr thingy;
...
thingy.assign(new int, true);
...
thingy.reset();

int i;
int_ptr pi;
...
pi.assign(&i, false);
...
pi.reset();