无题
发表于|更新于
|字数总计:1.4k|阅读时长:6分钟|阅读量:
unique_ptr
使用make_unique创建一个unique_ptr:
| 1
 | unique_ptr<int>unPtr1 = make_unique<int>(25);
 | 
此时若运行:
会输出指针所指向内存的地址,所以如果我们想输出它的值(25)的话,就要运行:
| 1
 | cout << *unPtr1 << endl;
 | 
unique_ptr不能共享
如果这么写会报错:
| 12
 
 | unique_ptr<int>unPtr1 = make_unique<int>(25);unique_ptr<int>unPtr2 = nPtr1;
 
 | 
唯一能做的就是更改内存地址的所有权,比如把所有权从unPtr1修改为unPtr2
| 1
 | unique_ptr<int>unPtr2 = move(unPtr1);
 | 
此时运行:
| 1
 | cout << *unPtr2 << endl;
 | 
会输出25  
此时之前的指针unPtr1就会变成空指针,如果你再试图访问它的话会得到指针异常
| 1
 | cout << *unPtr1 << endl; 
 | 
自动回收内存
所以不用再担心内存泄漏等情况  
unique_ptr将在它的作用域结束时被销毁,我们可以用它新建一个类指针来进行实验
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | class Myclass {public:
 MyClass() {
 cout << "Constructor invoked" << endl;
 }
 ~MyClass() {
 cout << "Destructor invoked" << endl;
 }
 };
 
 int main()
 {
 unique_ptr<MyClass>unPtr1 = make_unique<MyClass>();
 }
 
 | 
此时只会输出Constructor invoked,因为该指针的作用域(最近的花括号)就是main函数,main函数已经结束了,所以看不到析构函数的调用。
如果我们把他修改成:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | class Myclass {public:
 MyClass() {
 cout << "Constructor invoked" << endl;
 }
 ~MyClass() {
 cout << "Destructor invoked" << endl;
 }
 };
 
 int main()
 {
 {
 unique_ptr<MyClass>unPtr1 = make_unique<MyClass>();
 }
 }
 
 | 
此时Constructor invoked和Destructor invoked都会输出,证明析构函数被调用,内存得到释放。
shared_ptr
通过make_shared创建一个shared_ptr
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | class Myclass {public:
 MyClass() {
 cout << "Constructor invoked" << endl;
 }
 ~MyClass() {
 cout << "Destructor invoked" << endl;
 }
 };
 
 int main()
 {
 shared_ptr<MyClass>shPtr1 = make_shared<MyClass>();
 }
 
 | 
use_count()
可以通过shPtr1.use_count()查看这个共享指针(内存位置)有多少个所有者
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | class Myclass {public:
 MyClass() {
 cout << "Constructor invoked" << endl;
 }
 ~MyClass() {
 cout << "Destructor invoked" << endl;
 }
 };
 
 int main()
 {
 shared_ptr<MyClass>shPtr1 = make_shared<MyClass>();
 cout << "Shared count: " << shPtr1.use_count() << endl;
 }
 
 | 
共享同一个内存位置
尝试再新建一个共享指针共享同一个内存位置
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | class Myclass {public:
 MyClass() {
 cout << "Constructor invoked" << endl;
 }
 ~MyClass() {
 cout << "Destructor invoked" << endl;
 }
 };
 
 int main()
 {
 shared_ptr<MyClass>unPtr1 = make_shared<MyClass>();
 cout << "Shared count: " << shPtr1.use_count() << endl;
 shared_ptr<MyClass>unPtr2 = shPtr1;
 cout << "Shared count: " << shPtr1.use_count() << endl;
 }
 
 | 
我们也可以通过作用域测试来测试shared_ptr什么时候会被销毁
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | class Myclass {public:
 MyClass() {
 cout << "Constructor invoked" << endl;
 }
 ~MyClass() {
 cout << "Destructor invoked" << endl;
 }
 };
 
 int main()
 {
 shared_ptr<MyClass>unPtr1 = make_shared<MyClass>();
 cout << "Shared count: " << shPtr1.use_count() << endl;
 {
 shared_ptr<MyClass>unPtr2 = shPtr1;
 cout << "Shared count: " << shPtr1.use_count() << endl;
 }
 cout << "Shared count: " << shPtr1.use_count() << endl;
 }
 
 | 
如果修改为这样
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 
 | class Myclass {public:
 MyClass() {
 cout << "Constructor invoked" << endl;
 }
 ~MyClass() {
 cout << "Destructor invoked" << endl;
 }
 };
 
 int main()
 {
 {
 shared_ptr<MyClass>unPtr1 = make_shared<MyClass>();
 cout << "Shared count: " << shPtr1.use_count() << endl;
 {
 shared_ptr<MyClass>unPtr2 = shPtr1;
 cout << "Shared count: " << shPtr1.use_count() << endl;
 }
 cout << "Shared count: " << shPtr1.use_count() << endl;
 }
 }
 
 | 
此时智能指针被自动销毁,输出为:
| 12
 3
 4
 5
 
 | Constructor invokedShared count: 1
 Shared count: 2
 Shared count: 1
 Destructor invoked
 
 | 
weak_ptr
共享指针与弱指针的区别:
弱指针被赋予跟其它指针同样的内存地址时,不会增加所有者的数量(即上文中的Shared count不变)
我们使用弱指针来在内存中定位一个特定的对象,但是如果没有其它需要的话,弱指针将不会使该对象保持活动,而共享指针将使该对象保持活动
| 12
 3
 4
 5
 6
 7
 8
 
 | int main(){
 weak_ptr<int> wePtr1;
 {
 shared_ptr<int>shPtr1 = make_shared<int>(25);
 weakPtr1 = shPtr1;
 }
 }
 
 | 
首先我们必须清楚,这里的赋值方式有些不同,weak_ptr是在其下方作用域之外被定义的
此时我们通过断点来解释:
在第三行时,显示wePtr1为empty
在第五行时,该共享指针指向有一个强引用的内存位置,在这个内存位置上我们存储的值是25
在第六行时,显示弱指针也指向同样的存储的值为25的内存位置,此时该内存位置有一个强引用,一个弱引用
在第七行时,显示该内存位置只剩下一个弱引用,且弱指针显示为expired(过期)
此时,所有的该内存位置的所有者都被销毁了(由于作用域,此时共享指针已经被销毁),我们只剩下一个被分配的内存位置的地址。
也就是说,当该内存位置的最后一个强引用(即共享指针)被销毁时,它将被解除分配。
此时可能会有些迷糊啊,作为对比,如果我们把里面的弱指针也换成共享指针,那么结果就是依然有一个强引用存在与该内存位置,因为Ptr1是在其下方作用域之外被定义的。