指针理解和应用"/>
c++ void*指针理解和应用
c++ void*指针理解和应用
void*说明
void指针不指向任何数据类型,它属于一种未确定类型的过渡型数据。如果要访问实际存在的数据,必须将void指针强转成为指定一个确定的数据类型的数据,如int*、string*、Person*等。
void* p=nullptr;int *a=nullptr;
p=a;double *b=nullptr;
p=b;Person *per = new Person;
p = per;char c[16]={0};
p=c;void* 就像一张白纸,任何类型的指针都可以直接赋值给void*类型的指针;但是反过来int *a=nullptr;
a=p; //err
a=(int *)p;//需要强制类型转换Person *person2 = nullptr;
person2 = (Person *)p;
2.void指针只支持几种有限的操作:
a.与另一个指针进行比较;
b.向函数传递void指针或从函数返回void指针;
c.给另一个void指针赋值。
3.不允许使用void指针操作它所指向的对象,例如,不允许对void指针进行解引用。不允许对void*指针进行算术操作。例如:
几种常用的应用
1.函数传参时不确定类型,或者要支持多类型的传参
void function(int dataType, void* data) {// 根据dataType的不同值,进行不同的转换switch (dataType) {case 0:int* a = (int*)data;case 1:char* a = (char*)data;...}
}
2.当函数的返回值不考虑类型指关心大小的时候
void * memcpy(void *dest, const void *src, size_t len);
void * memset ( void * buffer, int c, size_t num );
//memcpy和memset对外接收任何类型的指针,这样是合理并且必要的,因为这是内存操作函数,
//是对bit进行操作的,考虑数据类型是没有任何意义的。
*2.关于delete void指针
1.void指向简单的系统内建类型直接只用delete void,比如下面代码所示:
void* p=nullptr;int *a=nullptr;
p=a;double *b=nullptr;
p=b;delete p;
2.void*所指向的对象在析构函数里要释放,进行此造作会丢失内存,因为它不执行析构函数,比如下面以下代码
class CEntity
{
public:CEntity(char flag);void setData(void *data);void setFlag(char flag);~CEntity();
private:void * m_data;char m_flag;
};CEntity::CEntity(char flag)
{m_flag = flag;cout<<"constructing entity "<<m_flag<<endl;;
}void CEntity::setData(void *data)
{m_data = data;}void CEntity::setFlag(char flag)
{m_flag = flag;
}CEntity::~CEntity()
{cout<<"destructing entity "<<m_flag<<endl;delete m_data;
}//以上这个类是没什么问题的,但是看以下的调用:
int main(int argc, char *argv[])
{CEntity * a = new CEntity();int ivalue = 5;int *pivalue = &ivalue;a->setFlag(true);a->setData(pivalue);delete a;CEntity * b = new CEntity();int ivalue2 = 6;int *pivalue2 = &ivalue2;b->setFlag(true);b->setData(pivalue2);void *vb = b;delete vb;return 0;
}
我们关心他的输出:
其输出为: constructing entity adestructing entity aconstructing entity b
可见,delete b 的时候没有释放m_data所指向的内存,没有执行析构函数。
这样会造成内存泄漏。
那么如何释放指向对象类型的void*指针呢?需要强制转换类型,然后进行delete。```cppCEntity * b = new CEntity('b');int ivalue2 = 6;int *pivalue2 = &ivalue2;b->setData(pivalue2);void *vb = b;//delete vb;delete (CEntity*)vb;其输出为: constructing entity adestructing entity aconstructing entity b destructing entity b
如果b对象的setData(a)这样使用,如何释放b对象内存呢、答案是b对象可以正常调用析构函数,但是其成员变量void指向的a对象内存永远释放不掉。因为delete a时会调用a的析构函数,在析构函数中本身类不知道void的真正的类型,所以delete void*时不会调用b的析构函数。代码和程序结果运行如下:
int main(int argc, char *argv[])
{CEntity * a = new CEntity('a');int ivalue = 5;int *pivalue = &ivalue;a->setData(pivalue);CEntity * b = new CEntity('b');b->setData(a);void *vb = b;delete (CEntity*)vb;return 0;
}其输出为: constructing entity adestructing entity aconstructing entity b
故类中的成员尽可能避免使用void变量,否则在类对象指针传入时会造成析构时void无法正确释放。
更多推荐
c++ void*指针理解和应用
发布评论