在C++中,动态内存的使用很容易出问题,因为要确保在正确的时间释放内存是极其困难的。有时会忘记释放内存,在这种情况下会产生内存泄露;有时在尚有指针引用内存的情况下就释放了它,在这种情况下就会产生引用非法内存的指针。
C++智能指针是包含重载运算符的类,其行为像常规指针,但智能指针能够及时、妥善地销毁动态分配的数据,并实现了明确的对象生命周期,因此更有价值。
unique_ptr 是从 C++ 11 开始,定义在
unique_ptr 之所以叫这个名字,是因为它智能指向一个对象,即当它指向其他对象时,之前所指向的对象会被摧毁。其次,当 unique_ptr 超出作用域时,指向的对象也会被自动摧毁。
std::unique_ptrp1(new int(5));
std::unique_ptrp2 = p1;// 编译会出错
std::unique_ptrp3 = std::move(p1);// 转移所有权, 现在那块内存归p3所有, p1成为无效的针.
p3.reset();//释放内存.
p1.reset();//无效
1 构造方法 std::unique_ptr::unique_ptr
// unique_ptr constructor example
#include
#include
int main () {
std::default_delete d;
std::unique_ptr u1;
std::unique_ptr u2 (nullptr);
std::unique_ptr u3 (new int);
std::unique_ptr u4 (new int, d);
std::unique_ptr u5 (new int, std::default_delete());
std::unique_ptr u6 (std::move(u5));
std::unique_ptr u7 (std::move(u6));
std::unique_ptr u8 (std::auto_ptr(new int));
std::cout << "u1: " << (u1?"not null":"null") << '\n';
std::cout << "u2: " << (u2?"not null":"null") << '\n';
std::cout << "u3: " << (u3?"not null":"null") << '\n';
std::cout << "u4: " << (u4?"not null":"null") << '\n';
std::cout << "u5: " << (u5?"not null":"null") << '\n';
std::cout << "u6: " << (u6?"not null":"null") << '\n';
std::cout << "u7: " << (u7?"not null":"null") << '\n';
std::cout << "u8: " << (u8?"not null":"null") << '\n';
return 0;
}
2、释放方法 std::unique_ptr::release
这里的释放并不是摧毁(destory)其指向的对象,而是将其指向的对象释放(release)出去,即转移该对象到另一个指针那里去。使用release 会切断unique_ptr 和它原来管理的对象的联系。release 返回的指针通常被用来初始化另一个智能指针或给另一个智能指针赋值。如果不用另一个智能指针来保存release返回的指针,程序就要负责资源的释放。
比如这个例子,auto_poiner执行release方法后,它就会变成一个nullptr,但是它把指向的对象转移到manual_pointer中了。
int main()
{
std::unique_ptr auto_pointer(new int);
int * manual_pointer;
*auto_pointer = 10;
manual_pointer = auto_pointer.release();
// (auto_pointer is now empty)
std::cout << "manual_pointer points to " << *manual_pointer << '\n';
std::cout << "auto_pointer points to " << (auto_pointer ? "not null" : "nullptr") << '\n';
delete manual_pointer;
return 0;
}
另一个例子
unique_ptr temp = get_me_some_foo(); // manages the object
Foo * ptr = temp.release(); // pointer to no-longer-managed object
temp.get_deleter() ( ptr );
3、重置方法 std::unique_ptr::reset
先将up所指对象释放,然后重置up的值
// unique_ptr::reset example
#include
#include
int main () {
std::unique_ptr up; // empty
up.reset(new int); // takes ownership of pointer
*up = 5;
std::cout << *up << '\n';
up.reset(new int); // deletes managed object, acquires new pointer
*up = 10;
std::cout << *up << '\n';
up.reset(); // deletes managed object
std::cout << "up to " << (up ? "not null" : "nullptr") << '\n';
return 0;
}
4、交换方法 std::unique_ptr::swap
// unique_ptr::swap example
#include
#include
int main () {
std::unique_ptr foo (new int(10));
std::unique_ptr bar (new int(20));
foo.swap(bar);
std::cout << "foo: " << *foo << '\n';
std::cout << "bar: " << *bar << '\n';
return 0;
}
5、自定义资源删除操作(Deleter)
// unique_ptr destructor example
#include
#include
int main () {
// user-defined deleter
auto deleter = [](int*p){
delete p;
std::cout << "[deleter called]\n";
};
std::unique_ptr foo (new int,deleter);
std::cout << "foo " << (foo?"is not":"is") << " empty\n";
return 0; // [deleter called]
}
unique_ptr不允许两个独占指针指向同一个对象,在没有裸指针的情况下,我们只能用release获取内存的地址,同时放弃对对象的所有权,这样就有效避免了多个独占指针同时指向一个对象。
而使用裸指针就很容器打破这一点
int main()
{
int *x(new int(2));
unique_ptr up1, up2;
//会使up1 up2指向同一个内存
up1.reset(x);
std::cout << "x to " << (x ? "not null" : "nullptr") << '\n';
std::cout << *x << '\n';
up2.reset(x);
std::cout << "x to " << (x ? "not null" : "nullptr") << '\n';
*up1 = 5;
std::cout << *up1 << '\n';
std::cout << *up2 << '\n';
std::cout << "x to " << (x ? "not null" : "nullptr") << '\n';
std::cout << *x << '\n';
}
另一个例子
int main()
{
int* p = nullptr; // null null null
p = std::unique_ptr(new int(5)).get();
std::cout << "p to " << (p ? "not null" : "nullptr") << '\n';
std::cout << *p << '\n';
}
所以,尽量避免智能指针和普通指针的混合,那样容易非常的乱,导致内存泄露,程序崩溃
参考:
https://blog.csdn.net/afei__/article/details/80670283
https://blog.csdn.net/qq_33266987/article/details/78784286