unique_ptr
创建方式
创建方式:
std::unique_ptr<int> fPtr1;//创建一个空指针,为分配空间
std::unique_ptr<int> fPtr2(new int(4));//使用普通指针进行初始化
std::unique_ptr<int> fPtr3 = std::make_unique<int>(4);//使用标准库去创建,推荐这样使用。可以处理一些异常安全的问题
//std::unique_ptr<int> fPtr4 = new int(4) ;//unique_ptr禁止了隐式类型转换,所以不能这么初始化
资源独占和移动
唯一指针,即非共享的,该指针指向的资源具有独占性,同一时刻只能有一个unique_ptr指针指向这个独占资源。
例如:下面声明一个类,包含了构造和析构函数:
class MyClass {
public:
MyClass() {
std::cout << "Construct function" << std::endl;
}
MyClass(const char* name): m_Name(name) {
std::cout << "Construct function: "<< m_Name << std::endl;
}
~MyClass() {
std::cout << "Distory function" << m_Name << std::endl;
}
const std::string* const GetName() const{
m_Name = "";
return &m_Name;
}
private:
mutable std::string m_Name;
};
我们声明一个unique_ptr后,不能把这个unique_ptr的值赋给其他的unique_ptr指针。unique_ptr指针的拷贝构造和赋值运算是被禁止。也就是一个指针对应的资源只能通过这个指针来访问。
unique_ptr虽然不能进行拷贝,但是其独占资源的所有权可以移动,使用std::move可以将一个unique_ptr指针的资源移动到另一个unique_ptr指针对象上,原有的unique_ptr将会被置位空。
例如:
int main()
{
{
std::unique_ptr<MyClass> uptr_1 = std::make_unique<MyClass>("1111");
//uptr_1 地址为:0x0000000000003FD9
std::unique_ptr<MyClass> uptr_3 = std::move(uptr_1);
//uptr_1 地址为:0x0000000000000000
//uptr_3 地址为:0x0000000000003FD9
}
}
资源的释放
可以把unique_ptr理解为作用域指针,当该指针超出其作用域后指针对象和其所拥有的独占资源就会被释放。我们在主函数中创建一个unique_ptr,当uptr_1 超出作用域后就会被析构,其占有的独占资源就会被释放。这点不同于share_ptr的指针引用计数,share_ptr只有当引用计数为0的时候共享资源才会被方式。
int main()
{
{
std::unique_ptr<MyClass> uptr_1 = std::make_unique<MyClass>("1111");
}
}
此外,我们还可以通过其他方式释放:
int main()
{
{
std::unique_ptr<MyClass> uptr_1 = std::make_unique<MyClass>("1111");
uptr_1.reset();//释放资源,将uptr_1置为nullptr
//uptr_1 = nullptr;//将uptr_1 置为空,就调用析构函数释放资源
//MyClass* tmp = uptr_1.release();//将uptr_1置为空,并返回一个指针,此时资源不会被释放,而是转为普通指针temp上
}
}
参考:
https://blog.csdn.net/lemonxiaoxiao/article/details/108603916
share_ptr
共享指针:采用引用计数对共享资源进行监控,只有当引用计数为0才会释放资源。
int main()
{
{
std::shared_ptr<MyClass> m1 = std::make_shared<MyClass>();
{
std::shared_ptr<MyClass> m2 = m1;
std::shared_ptr<MyClass> m3 = m1;
}
std::cout << "Hello World11111!\n";
m1 = nullptr;
std::cout << "Hello World!\n";
}
std::cout << "Hello World!\n";
}
上述代码,当m1=nullptr被调用时,只能指针引用计数变为0,此时会先调用MyClass的析构函数释放空间,之后才会打印后面的Hello World。
创建
//共享指针创建时可以自定义析构函数,可以是函数指针,也可以是lambda表达式。当引用计数为0时,析构函数会被调用,用来删除指针对象,释放空间
std::shared_ptr<int> p(new int(0), [=](int* p) {
delete p;
std::cout << "delete p\n";
});