frankfan的胡思乱想

学海无涯,回头是岸

智能指针与文件流

智能指针 C++文件流操作API

本章讲授的主要内容是智能指针的应用以及C++接口的文件操作。

因为C++文件操作相关API难用,相交C接口以及windows本地平台接口并没有带来相对的优势,因此本笔记不会记录C++文件操作的相关API

而C++中基本要杜绝『裸指针』的使用,推荐使用『智能指针』。

所谓智能指针,本质是通过添加一层包裹类,将这个类当做局部变量使用。局部变量超出作用域时编译器会调用其析构函数,因此在析构函数中配合『引用计数』来释放被包裹的类。

之所以要设计智能指针这样的类,本质的目的还是在于科学有效的管理堆内存。

被分配在堆中的内存何时被释放,是所有面向对象编程中(或者支持在堆中分配内存的语言中)必须要解决的问题。有的语言提供编译期的引用计数,有的是通过虚拟机的垃圾回收等机制。而C++并没有提供编译期的引用计数代码生成方案(如Objective-C),也没有提供垃圾回收机制,只提供用户态基于库函数的『智能指针』,理论上,用户自己也能实现属于自己的智能指针类,但是存在诸多繁复细节要考虑(如需要准确识别包裹的是对象还是对象数组等),因此并不推荐用户自行使用自定义的智能指针包裹类。直接使用语言库提供的指针智能类。


智能指针之share_ptr

被定义在堆上的对象,既可能被A指针引用,又可能被B指针引用,能够在各种函数调用中被传递,因此,当我们定义的对象符合可能被多个指针引用(持有)时,则需要使用share_ptr类

#include <iostream>
using namespace std;

class Node{
public:
  Node(){}
};

void handleNode(shared_ptr<Node> node){
  //do something...
}

int main(){
  
  //通过shared_ptr类包裹住分配在堆内存中的Node对象,shared_ptr是一个模板类,又被称为智能指针
  shared_ptr<Node> node(new Node);
  
  //之所以叫shared_ptr是因为这个类包裹的堆对象允许被多个对象引用持有,反言之,当我们定义的堆对象允许被多重持有时,则需要使用shared_ptr进行包裹
  shared_ptr<Node> node2 = node;
  
  handleNode(node2);
  
  //智能指针支持创建对象数组
 	shatrd_ptr<Node[]> nodes(new Node[3]);
  
  return 0;
}

被智能指针包裹后的堆裸指针不再需要手动进行delete释放对象,自动被shared_ptr管理了

除此外,当我们定义的堆对象不允许或者说只能被单个对象持有时,则需要使用unique_ptr

#include <iostream>
using namespace std;

class Node{
public:
  Node(){}
};

int main(){
  
  unique_ptr<Node> node(new Node);
  //当另一个对象需要持有堆对象node时,需要使用的语义是『转移』,也就是说堆对象始终只会被一个对象(指针)持有
  unique_ptr<Node> node2 = move(node);
  return 0;
}

智能指针内部也是基于『引用计数』原理对堆内存进行管理的。

但凡有引用计数的地方就有循环引用,循环引用产生的原因在于引用计数的无区别增加。因此需要能够控制引用计数是否增加,这时C++提供了另一个类weak_ptr,被weak_ptr包裹的堆对象引用计数并不会增加。通常,在处理循环引用时需要用到weak_ptr。

#include <iostream>
using namespace std;

class Node{
public:
  Node(){}
};

int main(){
  
  shared_ptr<Node> node(new Node);//此时node引用计数为1
  shared_ptr<Node> node2 = node;//此时node引用计数为2
  //weak_ptr并不会使得对象引用计数增加
  weak_ptr<Node> node3 = node2;////此时node引用计数依旧2
  return 0;
}

posted on 2021-12-28 00:17  shadow_fan  阅读(125)  评论(0编辑  收藏  举报

导航