C++智能指针

必须包含头文件#include <memory>

std::auto_ptr 在C++11中被废弃 采用所有权模型

std::auto_ptr<Class> className;
采用所有权模型,当值被其他auto_ptr赋值时,所有权交予他人,本指针变为空地址
例如:
std::auto_ptr<Class> className1(new Class()));
std::auto_ptr<Class> className2(className1);
此时所有权交给className2, className1指针变为空指针

如下图所示,打印指针为空

 

std::unique_ptr 采用所有权模型 唯一指针

std::unique_ptr<Class> className;
例如:
std::unique_ptr<Class> className1(new Class()));
std::unique_ptr<Class> className2(className1);
此时是非法的,会报编译错误unique_ptr比auto_ptr的策略更严格,不容易出错
如下图所示

使用移std::move(),能够将指针赋值给另外一个智能指针,当前智能指针变为空

 

 

std::unique_ptr可以充当函数的参数,以及返回值当参数

void Test(std::unique_ptr<std::string> str)
{
    std::cout << *str << std::endl;
}

int main()
{
    std::unique_ptr<std::string> str(new std::string("this is a test..."));
    Test(std::move(str));
    return 0;
}

当返回值,return语句不需要move的原因是根据C++11的语言规则编译器将自动尝试移动

std::unique_ptr<std::string> Test()
{
    std::unique_ptr<std::string> str(new std::string("this is a test..."));
    return str;
}

int main()
{
    std::unique_ptr<std::string> str = Test();

    std::cout << *str << std::endl;

    return 0;
}

std::unique_ptr 造成段错误

如下所示,此时新建两个唯一指针,同时指向int,当析构时就会造成二次析构,这就会造成析构两次,double free错误

class Test
{
public:
    ~Test()
    {
        qDebug() << "Destory Test";
    }
};

int main()
{
    Test *test = new Test();
    std::unique_ptr<Test> pTest1(test);
    std::unique_ptr<Test> pTest2(test);
    return 0;
}

std::shared_ptr 采用引用计数模型 智能更高的指针 共享指针

std::shared_ptr<Class> className;

每增加一个引用操作,shared_ptr内部计数会增加1

例如:

std::shared_ptr<Class> className1(new Class()));

std::shared_ptr<Class> className2(className1);

此时是引用计数为2,当引用计数,当指针过期时,引用计数减1,仅当最后一个指针过期时,才会调用delete释放资源,共享指针不是线程安全的

如下图所示

std::shared_ptr 创建的三种方式

std::shared_ptr<std::string> pTest{new std::string("Test")};
std::shared_ptr<std::string> pTest(new std::string("Test"));
std::shared_ptr<std::string> pTest = std::make_shared<std::string>("Test");

推荐:使用第三种方式进行创建,更快(一次复制),更安全

std::shared_ptr 放入容器中

如下所示,此时的引用计数为2,在创建时引用计数为1,在加载进容器时,引用计数为2,向容器中插入共享指针,只是其引用计数会增加,两个指针同时指向一个对象

    std::vector<std::shared_ptr<std::string>> testVector;
    std::shared_ptr<std::string> pTest = std::make_shared<std::string>("Test");
    testVector.push_back(pTest);

std::shared_ptr 造成段错误

如下所示,此时新建两个共享指针,同时指向Test,但此时的pTest1和pTest2的引用计数都为1,这就会造成析构两次,double free错误

class Test
{
public:
    ~Test()
    {
        qDebug() << "Destory Test";
    }
};

int main()
{
    Test *pTest = new Test();
    std::shared_ptr<Test> pTest1(pTest);
    std::shared_ptr<Test> pTest2(pTest);

    std::cout << "Use Count pTest1:"<<  pTest1.use_count() << std::endl;
    std::cout << "Use Count pTest2:"<<  pTest2.use_count() << std::endl;
    return 0;
}

std::shared_ptr使用std::enable_shared_from_this和shared_from_this()

std::enable_shared_from_this 能让一个对象(假设其名为 t ,且已被一个 std::shared_ptr 对象 pt 管理)安全地生成其他额外的 std::shared_ptr 实例(假设名为 pt1, pt2, ... ) ,它们与 pt 共享对象 t 的所有权。

       若一个类 T 继承 std::enable_shared_from_this<T> ,则会为该类 T 提供成员函数: shared_from_this 。 当 T 类型对象 t 被一个为名为 pt 的 std::shared_ptr<T> 类对象管理时,调用 T::shared_from_this 成员函数,将会返回一个新的 std::shared_ptr<T> 对象,它与 pt 共享 t 的所有权。

class Test : public std::enable_shared_from_this<Test>
{
public:
    ~Test()
    {
        qDebug() << "Destory Test";
    }

    std::shared_ptr<Test> getSharedPtr()
    {
        return shared_from_this();
    }
};


int main()
{
    Test *pTest = new Test();
    std::shared_ptr<Test> pTest1(pTest);
    std::shared_ptr<Test> pTest2(pTest->getSharedPtr());

    std::cout << "Use Count pTest1:"<<  pTest1.use_count() << std::endl;
    std::cout << "Use Count pTest2:"<<  pTest2.use_count() << std::endl;
    return 0;
}

此时不会造成段错误的情况,只释放了一次,且引用计数为2

强制类型转换

如下所示,将int型指针初始化为void型指针,在后面使用时使用static_pointer_cast强制转换回来

    std::shared_ptr<void> pTest = std::make_shared<int>(100);
    std::cout << *std::static_pointer_cast<int>(pTest);

std::static_pointer_cast

std::dynamic_pointer_cast

std::const_pointer_cast

std::reinterpret_pointer_cast()

对于智能指针的强制类型转换,智能使用上面四种进行强制类型转换,而不可使用C风格的static_cast<new_type> (expression) :

dynamic_cast<new_type> (expression) :

const_cast<new_type> (expression) :

reinterpret_cast <new_type> (expression) :

这四种强制类型转换

智能指针的销毁

定义删除器,对智能指针进行删除,如下所示使用Lambda表达式,销毁智能指针

class Test
{
public:
    ~Test()
    {
        qDebug() << "Destory Test";
    }
};

int main()
{
    std::shared_ptr<Test> pTest1(new Test(), [](Test *test)
    {
        std::cout << "Lambda delete" << std::endl;
        delete test;
    });
    return 0;
}
或者
void delFunction(Test *test)
{
    std::cout << "Lambda delete" << std::endl;
    delete test;
}

int main()
{
    std::shared_ptr<Test> pTest1(new Test(), delFunction);
    return 0;
}

再或者

int main()
{
    std::shared_ptr<Test> pTest1(new Test(), std::default_delete<Test>());
    return 0;
}

前两种是一样的,第三种使用std::default_delete对智能指针进行删除

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值