weakptr-void sharedptr-void知多少及智能指針的類型轉換

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章