void*裸指针的使用及转换
我们知道,在使用裸指针时,对于那些不确定的类型指针,我们可以用void*
来进行指向.
真正知道了类型之后,需要进行转换.具体的转换方式有:
static_cast<T*>
const_cast<T*>
reinterpret_cast<T*>
dynamic_cast<T*>
-
static_cast
:
显式转换,只要你知道要转换的类型,且不包含底层const都可以使用.这也是最常用的一个转换:double d = 2; void *p = &d; double *dp = static_cast<double *>(p);
-
const_cast
:
只能改变底层const,即可以将常量转为非常量(去掉const属性),但是对它进行修改仍然是错误的.常常用于函数重载.const char *cp; char *p = static_cast<char *>(cp); //错误,static_cast不能去掉const属性 static_cast<string>(cp); //正确,转换为string类型 const_cast<string>(cp); //错误,只能修改const属性 char *p = const_cast<char*>(cp); //正确,去掉const属性
-
reinterpret_cast
在bit层面上,为要转换的指针提供重新解释.即:int *ip; char *pc = reinterpret_cast<char *> ip;
此时
string str(pc)
就会出现很多问题,尽管在编译器看来没有问题,因为用reinterpre_cast把原本指向int的指针转为指向char了,不会有warning和error,故这类转换最好不用. -
dynamic_cast
RTTI功能主要由typeid运算符
(返回表达式类型)和dynamic_cast
完成.
dynamic_cast
就是将基类的指针或引用安全的转换为派生类的指针或者引用.
用法如下:A *a; dynamic_cast<B *>(a); dynamic_cast<B&>(aobj); dynamic_cast<B&&>(arval);
A必须是B的公有派生类,或者A是B的公有基类,或者是A==B.只有这几个才能转换成功.
shared_ptr< void >的转换
先看一个例子吧:
class A {
public:
A():a(0){cout<<"A constructor ! "<<endl;}
~A(){cout<<"A destroy!"<<endl;}
void printA(){cout<<"A data "<< a <<endl;}
private:
int a;
};
int main()
{
std::shared_ptr<A> aptr = std::make_shared<A>();
std::weak_ptr<void> wptr;
wptr = aptr;
cout<<"A ptrcount: "<<aptr.use_count()<<endl;
//wptr->printA();//错误,weak_ptr去访问对象应该用.lock(),即首先检查对象是不是存在,而后在访问
std::shared_ptr<void> vptr = wptr.lock();
cout<<"A ptrcount: "<<aptr.use_count()<<endl;
//vptr->printA();//错误,此时vptr无法调用printA()
std::shared_ptr<A> aptr2 = static_pointer_cast<A>(vptr);
cout<<"A ptrcount: "<<aptr.use_count()<<endl;
aptr2->printA();
return 0;
}
最终输出:
即shared_ptr<void>
其实和void*
用法一样的,但是这里要注意的是shared_ptr<void>
被shared_ptr<A>
初始化,同样仍旧增加计数.且有如下例子:
#include <iostream>
using namespace std;
class Foo
{
public:
Foo() { cout << "Foo()" << endl; }
~Foo() { cout << "~Foo()" << endl; }
};
int main(int argc, const char * argv[]) {
shared_ptr<void> vptr = shared_ptr<Foo>(new Foo);
return 0;
}
输出:
Foo()
~Foo()
所以shared_ptr<void>
仍旧能工作.那么为何能工作呢?
因为不像void一样,我们肯定不能直接delete 一个void指针,因为谁知道它指向哪.
工作原理戳这里
参考资料
https://stackoverflow.com/questions/5913396/why-do-stdshared-ptrvoid-work
https://www.cnblogs.com/imjustice/p/how_shared_ptr_void_works.html