C++ 删除指针的哪种方式:删除/删除[]/自由?
我正在实现standart模板树结构,遇到了一个小问题 每个节点将持有指向某些数据的指针的想法。稍后为了正确删除元素,我需要知道它是单个指针还是指向数组的指针 在我的C++ 删除指针的哪种方式:删除/删除[]/自由?,c++,pointers,C++,Pointers,我正在实现standart模板树结构,遇到了一个小问题 每个节点将持有指向某些数据的指针的想法。稍后为了正确删除元素,我需要知道它是单个指针还是指向数组的指针 在我的树->ReleaseMemory()方法中,我有以下代码: if (node->_data != NULL) { switch (_destructionMethod){ case tree_delete: delete node->_data; br
树->ReleaseMemory()方法中,我有以下代码:
if (node->_data != NULL) {
switch (_destructionMethod){
case tree_delete:
delete node->_data; break;
case tree_deleteList:
delete [] node->_data; break;
case tree_free:
free(node->_data); break;
}
}
其中\u destructionMethod
已在节点初始化期间设置。
是否有任何方法可以选择正确的析构函数,而无需在初始化过程中为其在特殊变量中预定义它
谢谢 根本不要这样做。使用智能指针,如Cux> SyddYPPT/<代码>,从C++ 0x或Boost或如果不是选项,< C++ >代码> AutoPPTR <代码>。如果可以有多个对象,请考虑使用<代码> STD::vector < /代码> .<
手动资源管理很混乱,很难正确进行 根本不要这样做。使用智能指针,如Cux> SyddYPPT/<代码>,从C++ 0x或Boost或如果不是选项,< C++ >代码> AutoPPTR <代码>。如果可以有多个对象,请考虑使用<代码> STD::vector < /代码> .<
手动资源管理很混乱,很难正确进行 第一基础:
使用new
分配内存时使用delete
:
int *p = new int;
int *a = new int[10];
//...
delete p;
delete []a; //note the difference!
使用malloc
分配内存时使用free
:
int *p = (int*)malloc(sizeof(int) * 1);
int *a = (int*)malloc(sizeof(int) * 10);
//...
free(p);
free(a); //no difference!
现在你的问题是:
在初始化过程中,我是否可以选择正确的析构函数,而不必在特殊变量中预先定义它
考虑一下。这意味着,编写分配器,将分配和解除分配封装在一个类中,并在代码中一致地使用它。第一个基本:
使用new
分配内存时使用delete
:
int *p = new int;
int *a = new int[10];
//...
delete p;
delete []a; //note the difference!
使用malloc
分配内存时使用free
:
int *p = (int*)malloc(sizeof(int) * 1);
int *a = (int*)malloc(sizeof(int) * 10);
//...
free(p);
free(a); //no difference!
现在你的问题是:
在初始化过程中,我是否可以选择正确的析构函数,而不必在特殊变量中预先定义它
考虑一下。也就是说,编写一个将分配和释放封装在类中并在代码中一致使用的allocator
。不,没有可移植的方法来找出特定指针最初来自哪个分配器。不,没有可移植的方法来找出某个特定指针最初来自哪个分配器。没有方法通过询问指针来找出它是如何分配的,但是一个常见的习惯用法是让分配的对象自己负责自己的破坏。不过,看起来您的对象类型并不是所有的类类型,所以您需要包装它们才能做到这一点。例如:
class destroyable_node
{
virtual void destroy() = 0;
};
template <typename T> class object_node : public destroyable_node
{
private:
T * value_;
public:
// Presumes T is copy-constructable.
object_node(T value) : value_( new T(value) ) {}
operator T&() {return value_;}
operator T const &() const {return value_;}
void destroy() {delete value_;}
};
template<typename T> class array_node : public destroyable_node
{
private:
T * value_;
public:
array_node(T[] value)
: value_( new T[ sizeof(value)/sizeof(T) ] )
{
std::copy(value, value + sizeof(value)/sizeof(T), value_);
}
operator T*() {return value_;}
operator T const *() const {return value_;}
void destroy() {delete[] value_;}
};
类可销毁_节点
{
虚空销毁()=0;
};
模板类对象\u节点:公共可销毁\u节点
{
私人:
T*值u;
公众:
//假定T是可复制构造的。
对象\节点(T值):值\新的T(值)){
运算符T&({返回值}
运算符T常量&()常量{返回值}
void destroy(){删除值}
};
模板类数组_节点:公共可销毁_节点
{
私人:
T*值u;
公众:
数组_节点(T[]值)
:value_uT(新的[sizeof(value)/sizeof(T)])
{
std::copy(value,value+sizeof(value)/sizeof(T),value_);
}
运算符T*(){返回值}
运算符T常量*()常量{返回值}
void destroy(){delete[]值}
};
…等等。没有办法通过询问指针来了解它是如何分配的,但是一个常见的习惯用法是让分配的对象自己负责自己的破坏。不过,看起来您的对象类型并不是所有的类类型,所以您需要包装它们才能做到这一点。例如:
class destroyable_node
{
virtual void destroy() = 0;
};
template <typename T> class object_node : public destroyable_node
{
private:
T * value_;
public:
// Presumes T is copy-constructable.
object_node(T value) : value_( new T(value) ) {}
operator T&() {return value_;}
operator T const &() const {return value_;}
void destroy() {delete value_;}
};
template<typename T> class array_node : public destroyable_node
{
private:
T * value_;
public:
array_node(T[] value)
: value_( new T[ sizeof(value)/sizeof(T) ] )
{
std::copy(value, value + sizeof(value)/sizeof(T), value_);
}
operator T*() {return value_;}
operator T const *() const {return value_;}
void destroy() {delete[] value_;}
};
类可销毁_节点
{
虚空销毁()=0;
};
模板类对象\u节点:公共可销毁\u节点
{
私人:
T*值u;
公众:
//假定T是可复制构造的。
对象\节点(T值):值\新的T(值)){
运算符T&({返回值}
运算符T常量&()常量{返回值}
void destroy(){删除值}
};
模板类数组_节点:公共可销毁_节点
{
私人:
T*值u;
公众:
数组_节点(T[]值)
:value_uT(新的[sizeof(value)/sizeof(T)])
{
std::copy(value,value+sizeof(value)/sizeof(T),value_);
}
运算符T*(){返回值}
运算符T常量*()常量{返回值}
void destroy(){delete[]值}
};
…等等。也许更好的设计是用三个具体的子类实现容器使用的抽象接口,这些子类知道它们持有指向什么类型的指针。您的容器只需在基类中调用destroy()方法,并让派生类担心调用正确的析构函数。也许更好的设计是使用三个具体的子类实现容器使用的抽象接口,这些子类知道它们持有指向哪种类型的指针。您的容器只需在基类中调用destroy()方法,并让派生类担心调用正确的析构函数。尽管这是可能的,但根据情况使用原始指针/数据可能仍然有效。但是如果是这样的话——我认为除非你从一开始就处理分配,否则不应该实现一个发布。注意C++0xC中存在boost::checked\u array\u deleter
和std::default\u delete
,并避免在STL容器中使用std::auto\u ptr:虽然这可能,但使用原始指针/数据仍然有效视情况而定。但是如果是这样的话——我认为除非你从一开始就处理分配,否则不应该实现一个发布。注意C++0xC中存在boost::checked\u array\u deleter
和std::default\u delete
,并避免将std::auto\u ptr与S一起使用