再探 智能指针
使用任何一项工具,都需要承担代价与风险的。
1、一个裸的指针不要用两个shared_ptr管理,unique_ptr也是,它们都会认为自己独占这个资源,你等释放的时候试试看。
2、用weak_ptr打破循环引用。
3、当需要在类的内部接口中,如果需要将this作为智能指针来使用的话,需要用该类派生自enable_shared_from_this。
enable_shared_from_this和shared_from_this在构造和析构中是不能使用的,在某些情况下也不能使用,因为构造的时候类还未生成好,析构的时候类快完蛋了都没有意义。
#include <cassert>
#include <memory>
#include <iostream>
class Parent;
typedef std::shared_ptr<Parent> ParentPtr;
typedef std::weak_ptr<Parent> WeakParentPtr;
class Child : public std::enable_shared_from_this<Child> {
public:
WeakParentPtr father;
~Child();
Child();
void checkRelation();
};
typedef std::shared_ptr<Child> ChildPtr;
typedef std::weak_ptr<Child> WeakChildPtr;
class Parent : public std::enable_shared_from_this<Parent> {
public:
WeakChildPtr son;
~Parent();
Parent();
void checkRelation();
};
void handleChildAndParentRef(const Parent& p, const Child& c) {
auto cp = c.father.lock();
auto pc = p.son.lock();
if (cp.get() == &p && pc.get() == &c) {
std::cout << "right relation\n";
}
else {
std::cout << "oop!!!!!\n";
}
}
void handleChildAndParent(const ParentPtr& p, const ChildPtr& c) {
auto cp = c->father.lock();
auto pc = p->son.lock();
if (cp == p && pc == c) {
std::cout << "right relation\n";
}
else {
std::cout << "oop!!!!!\n";
}
}
Child::Child() { std::cout << "hello child\n"; }
Parent::Parent() { std::cout << "hello parent\n"; }
Child::~Child() { std::cout << "bye child\n"; }
Parent::~Parent() { std::cout << "bye parent\n"; }
void Parent::checkRelation() {
auto ps = son.lock();
if (ps) {
// this
handleChildAndParent(shared_from_this(), ps);
}
std::cout << "after call checkRelation\n";
}
void Child::checkRelation() {
// we call handleChildAndParent
}
void testParentAndChild() {
Parent pp;
ParentPtr p(new Parent());
ChildPtr c(new Child());
p->son = c; // c.use_count() == 2 and p.use_count() == 1
c->father = p; // c.use_count() == 2 p.use_count() == 2
p->checkRelation();
}
int main() {
testParentAndChild();
}
4、shared_ptr,weak_ptr和裸指针相比会大很多,并且效率上会有影响,尤其是在多线程模式下。
关于这点自己实现一个智能指针就知道了。
一个shared_ptr在空间上至少是三个裸指针的大小(24个字节),本身有引用还要配合weak_ptr使用所以要保存多少该指针的引用。如下生成既有对象的new还有本身的new:
ObjectPtr obj3(new Object(2));
ObjectPtr obj4 = obj3进行拷贝时时间效率会慢很多
可以用以下方式减少空间
ObjectPtr obj5 = std::make_shared<Object>(3);
//ObjectPtr obj5(new Object(3));
5、如果有可能,优先使用类的实例,其次万不得已使用std::unique_ptr,再万不得已使用std:shared_ptr。
用unique_ptr和用shared_ptr一样为了防止处理某些异常时无法调用delete释放资源的情况,在同一个特定的时刻只会有一个unique_ptr来管理一份资源没有共享模式,所以拷贝构造函数,=符号拷贝操作等是不存在的。
由于unique_ptr的唯一性所以要转移资源可以transfer传值,只能调用obj的右值引用而不能用左值,transfer函数执行完就释放了,调用了transfer后原有的会变成空指针不再管理。
#include <cassert>
#include <memory>
#include <iostream>
typedef int Object;
typedef std::unique_ptr<Object> UniqueObjectPtr;
typedef std::shared_ptr<Object> SharedObjectPtr;
void print(const UniqueObjectPtr& obj) {}
void transfer(UniqueObjectPtr obj) {
std::cout << obj << std::endl;
}
void uniquePtr() {
UniqueObjectPtr obj(new Object(1));
auto p = obj.get(); // operator bool
if (p) {
std::cout << p << std::endl;
}
// better
if (obj) {
std::cout << obj << std::endl;
}
// operator -> *
std::cout << p << obj << std::endl;
p = obj.release();
delete p;
obj.reset();
obj.reset(new Object(2)); // obj.reset();
// UniqueObjectPtr(const UniqueObjectPtr&) = delete
// UniqueObjectPtr(UniqueObjectPtr&&) = default
transfer(std::move(obj));
assert(obj == nullptr);
//std::cout << obj->id() << std::endl;
obj.reset(new Object(4));
SharedObjectPtr sharedObj(std::move(obj));
assert(obj == nullptr);
// shared_ptr weak_ptr enable_shared_from_this
// unique_ptr
}
6、智能指针只能表示所有权,如果遇到某些复杂的数据结构,或者所有权不明确的场景,还是得裸指针来。
也很好举例,用智能指针写个二叉树试试。
好了就说到这儿吧,再说多了怕是以后都不敢用了。
今天之所以要写这么一篇,是最近看智能指针的好处被吹的天花乱坠的让我都有点想把以前裸指针的代码全改成智能指针了。
但是呢,不要忘了我们开头的那句话哦。
相关文章
- Effective C++第17条:要在单独的语句中使用智能指针来存储由new创建的对象
- 活动 | 共谋新机遇,共话新突破——「机器人智能论坛」将于8月27日线上举办
- 亚信科技、清华AIR、英特尔成功举办WAIC智能算网与绿色计算论坛
- GTC2022精彩讲座预告|智能视频分析及智能制造
- 【C++】简单实现C++11的三种智能指针
- ue4 弱指针_智能指针如何实现自动释放
- 别再用XShell了!这款终端工具绝对惊艳,超级智能,太香了!
- C++智能指针
- AI好奇心,不只害死猫!MIT强化学习新算法,智能体这回「难易通吃」
- 如何搭建春节值班智能通知方案
- 煤矿人员工服着装智能识别监测系统
- Rust学习笔记Day18 智能指针Cow/MutexGuard
- 一天一个离职小技巧之智能指针
- 【C++ 语言】智能指针 引入 ( 内存泄漏 | 智能指针简介 | 简单示例 )
- 智能指针
- 大数据与Oracle驱动的智能创新(大数据和oracle)
- C++11 weak_ptr智能指针(一看即懂)
- 打造世界领先的智能运维大脑,必示科技获顺为资本数千万A轮融资
- LIFX智能灯泡漏洞泄露WIFI密码
- 新资产管理时代,我们需要怎样的智能投顾? | 雷锋网公开课
- 「唯物」智酷的CEO姚震想用智能键盘来取代一体机
- 架构模型基于Oracle的智能创新(oracle modle)
- 爱奇艺智能“追光”、哥伦布计划发布,VR能否跨越鸿沟?
- 寒武纪智能处理器微架构和指令集进一步升级
- 浅析Boost智能指针:scoped_ptrshared_ptrweak_ptr