四种智能指针的使用
auto_ptr<>, unique_ptr<>, shared_ptr<>, weak_ptr<>
参考:
https://changkun.de/modern-cpp/zh-cn/05-pointers/
================================================
1. auto_ptr<>
#include<memory> #include <iostream> using namespace std; struct Test { /* data */ int ta = 1; std::string ts = "HelloCpp"; }; int main() { auto_ptr<Test> p1(new Test()); cout << p1.get()->ta << endl; cout << (*p1).ta << endl; auto_ptr<Test> p2 = p1; if (p1.get() != nullptr) { cout << p1.get()->ta << endl;} else {cout << "p1 is nullptr!!!" << endl;} cout << p2.get()->ta << endl; p2.reset(new Test()); cout << p2.get()->ta << endl; Test* p3 = p2.release(); // release() 返回一个指针 cout << p3->ts << endl; p2.reset(); // reset() 会把当前智能指针内部的指针置0,或者输入新指针,如 p2.reset(Test*) cout << p2.get() << endl; }
2. shared_ptr<>
- 引用计数规则
#include<memory> #include <iostream> using namespace std; struct Test { /* data */ int ta = 1; std::string ts = "HelloCpp"; }; int main() { std::shared_ptr<Test> a = std::make_shared<Test>(); Test* pa = a.get(); // 获得 shared_ptr 对象内部包含的普通指针 cout << a->ta << endl; cout << a->ts << endl; cout << (*a).ta << endl; cout << (*a).ts << endl; cout << pa->ta << endl; cout << pa->ts << endl; cout << "============" << endl; cout << a.unique() << endl; //判断当前是否还有其他的share_ptr对象指向它,返回bool值 cout << (a) << endl; cout << a.use_count() << endl; a.reset(); cout << a.use_count() << endl; }
3. unique_ptr<>
- make_unique 的实现
-
template<typename T, typename ...Args> std::unique_ptr<T> make_unique(Args&& ...args) { return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
#include <iostream>
#include <memory> using namespace std; struct Foo { Foo() {std::cout << "Foo ctor" << std::endl;} ~Foo() {std::cout << "Foo dtor" << std::endl;} void foo() {std::cout << "Foo function" << std::endl;} }; void fun(const Foo&) { std::cout << "fun(const Foo&)" << std::endl; } int main() { std::unique_ptr<Foo> p1(std::make_unique<Foo>()); // std::make_unique<> 在C++14后加入 fun(*p1); if (p1) p1->foo(); cout << "==========" << endl; std::unique_ptr<Foo> p2(std::move(p1)); fun(*p2); fun(*p1); cout << p2.get() << endl; cout << p1.get() << endl; if (p2) p2->foo(); if (p1) p1->foo(); cout << "==========" << endl; p1 = std::move(p2); fun(*p2); fun(*p1); cout << p2.get() << endl; cout << p1.get() << endl; if (p2) p2->foo(); if (p1) p1->foo(); }
输出结果:
Foo ctor
fun(const Foo&)
Foo function
==========
fun(const Foo&)
fun(const Foo&)
0x130deb0
0
Foo function
==========
fun(const Foo&)
fun(const Foo&)
0
0x130deb0
Foo function
Foo dtor
4. weak_ptr<>
引入weak_ptr的原因:解决share_ptr 相互引用时出现的引用计数不为0导致的内存泄漏问题。
#include <iostream> #include <memory> using namespace std; struct A; struct B; struct A { /* data */ std::shared_ptr<B> pB; ~A() { std::cout << "Destroy A" << std::endl; } }; struct B { /* data */ std::shared_ptr<A> pA; //解决内存泄漏的办法是: std::weak_ptr<A> pA; ~B() { std:cout << "Destroy B" << std::endl; } };
void func(shared_ptr<A>& a, shared_ptr<B>& b) { cout << "a.use_cout() " << a.use_count() << endl; cout << "b.use_cout() " << b.use_count() << endl; a->pB = b; b->pA = a; cout << "a.use_cout() " << a.use_count() << endl; cout << "b.use_cout() " << b.use_count() << endl; } int main() {
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
func(a, b);
cout << "a.use_cout() " << a.use_count() << endl;
cout << "b.use_cout() " << b.use_count() << endl;
return 0;
}
输出结果:
a.use_cout() 1
b.use_cout() 1
a.use_cout() 2
b.use_cout() 2
此时,当 main() 函数结束以后,a 和 b 被销毁,但是原本来在 a 和 b 类中的智能指针 pA 和 pB 仍然指向对方,即两者的计数都为 1,因此造成内存泄漏。
解决办法是将其中一个 智能指针类成员改成 weak_ptr 类型,即弱引用指针,weak_ptr不会引起计数增加。