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