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

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