无题
发表于|更新于
|字数总计: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不能共享
如果这么写会报错:
1 2
| 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将在它的作用域结束时被销毁,我们可以用它新建一个类指针来进行实验
1 2 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函数已经结束了,所以看不到析构函数的调用。
如果我们把他修改成:
1 2 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
1 2 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()查看这个共享指针(内存位置)有多少个所有者
1 2 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; }
|
共享同一个内存位置
尝试再新建一个共享指针共享同一个内存位置
1 2 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什么时候会被销毁
1 2 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; }
|
如果修改为这样
1 2 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; } }
|
此时智能指针被自动销毁,输出为:
1 2 3 4 5
| Constructor invoked Shared count: 1 Shared count: 2 Shared count: 1 Destructor invoked
|
weak_ptr
共享指针与弱指针的区别:
弱指针被赋予跟其它指针同样的内存地址时,不会增加所有者的数量(即上文中的Shared count不变)
我们使用弱指针来在内存中定位一个特定的对象,但是如果没有其它需要的话,弱指针将不会使该对象保持活动,而共享指针将使该对象保持活动
1 2 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是在其下方作用域之外被定义的。