说我有这样的指针:
int *thingy;
在某些时候,可能会或可能不会调用此代码:
thingy=new int;
我如何知道我是否可以这样做:
delete thingy;
我可以为每个指针使用bool
,并在每次使用true
时将bool标记为new
,但是我有很多指针,这会非常笨拙。
如果我没有在new
上拨打thingy
,则在其上调用delete
可能会导致崩溃,对吗?
我搜索了很多,但找不到明显符合我情况的答案。
编辑:我需要能够delete
指向我喜欢的指针多次,而指针不一定指向任何数据。如果这是不可能的,我将不得不重新编写我的代码。
答案 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头控制。因此,存储区域的实际地址可以变化。但是你可以确定这些地区的位置:
获取每个区域的地址范围后,您可以区分指向堆数据的指针(其中删除是合适的)和指向堆栈数据的指针。这允许您区分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();