嵌入式C++(七)

简介: 嵌入式C++(七)

一 智能指针


1.1 手动初始化


注意:share_ptr p = new int(10); //错误
share_ptr是explicit,不能进行隐式类型转换,只能直接初始化


1.1.1 make_shared


0a2653c851af460fa595bd959398a8f1.png

//功能:在堆区可以动态分配对象,并返回一个share_ptr(推荐,安全,高效)(构造方法初始化)
  auto p = std::make_shared<string>("helloworld");
  shared_ptr<int> p1 = make_shared<int>(5);
  cout << *p1 << endl;
  shared_ptr<string> ps = make_shared<string>("hello world");
  cout << *ps << endl;
  //手动初始化和使用make_shared函数模板初始化有什么区别?
  //开销小,效率高(数据和引用计数存在同一个空间)
  //构造函数初始化:数据和引用计数不再同一段空间,需要间接访问
  shared_ptr<A> a1 = make_shared<A>();
  shared_ptr<A> a2(a1);


1.2 常规操作


1.2.1 use_count()


功能:返回有多少个智能指针指向某个对象(引用计数的个数)
用途:主要用于调试


shared_ptr<A> a1 = make_shared<A>();
shared_ptr<A> a2(a1);
cout << a2.use_count() << endl;  //返回当前有多少个指针指向当前对象或者空间


1.2.2 unique();


功能:是否该智能指针独占某个对象,独占返回true,否则返回false;


if (a1.unique())  //判断当前指针是否独享(只有它自己指向该对象)或者空间
  {
  cout << "a1 is unique ptr" << endl;
  }


1.2.3 reset


功能:判断当前指针是否独享该对象,如果独享,则释放该对象,否则将该指针置为NULL,并将引用计数器减一
用法:reset()或者reset(参数)


//判断当前指针是否独享该对象,如果独享,则释放该对象,并使该指针指向形参所对应的空间
  a1.reset(new A(10));
  //shared_ptr<A> pa(new A(188));
  //a1.reset(pa);
  cout << a1->m_a << endl;


1.2.4 解引用


获取智能指针指向的对象,并对其操作
get(); //获取智能指针中保存的裸指针。


shared_ptr<int> pd = make_shared<int>(5);
Test(pd.get());


1.2.5 指定删除器


功能:有些情况,默认删除器处理不了(share_ptr管理的动态数组)
 需要我们自己指定删除器,调用删除器函数释放空间


//指定删除器:当删除器不起作用的时候,需要自己指定删除器 void(*)(T*)
//shared_ptr<A> pa(new A[3]);  //delete pa --->应该是delete []pa;
//shared_ptr<A[]> pa(new A[3]);
//shared_ptr<A> pa(new A[3], Mydelete);
shared_ptr<A> pa(new A[3], default_delete<A[]>());


1.2.6 lambda 表达式


shared_ptr<A> pa(new A[3], [](A*a) {
  delete[]a;    //lambda表达式
  });


1.2.7 移动语义


shared_ptr<A> pa(new A(5));
  const shared_ptr<A> &rpa = move(pa);
  //shared_ptr<A> &&rpa = move(pa);
  cout << "***************"<<endl;
  //pa = nullptr;
  cout << pa.use_count() << endl;
  cout << rpa.use_count() << endl;


#include <iostream>
#include <memory>
#include <string>
using namespace std;
class A
{
public:
  A()
  {
  cout << "A的无参构造" << endl;
  }
  A(int n)
  {
  m_a = n;
  cout << "A的有参构造" << endl;
  }
  ~A()
  {
  cout << "A的析构函数" << endl;
  }
public:
  int m_a;
};
shared_ptr<A> test()
{
  shared_ptr<A> temp(new A);
  return temp;
}
void Func(shared_ptr<A> temp)
{
  cout << temp->m_a << endl;
}
void Test(int *p)
{
}
void Mydelete(A *pa)
{
  delete[]pa;
}
int main(void)
{
#if 0
  //int *p = new int(5);  //p是裸指针
  //shared_ptr<int> p = new int(5); //初始化:调用类型转换构造函数 explicit
  shared_ptr<int> p(new int(5));
  cout << *p << endl;
  shared_ptr<string> s(new string("helloworld"));
  cout << *s << endl;
  int num = 100;
  //shared_ptr<int> p2(&num);   //智能指针常用于堆空间,指向栈空间的时候,会导致内存释放两次
  //A *pa = new A(100);
  //delete pa;
  shared_ptr<A> pa(new A);
  shared_ptr<A> res = test();
  Func(pa);
  shared_ptr<A> pa2(pa);
  //功能:在堆区可以动态分配对象,并返回一个share_ptr(推荐,安全,高效)(构造方法初始化)
  auto p = std::make_shared<string>("helloworld");
  shared_ptr<int> p1 = make_shared<int>(5);
  cout << *p1 << endl;
  shared_ptr<string> ps = make_shared<string>("hello world");
  cout << *ps << endl;
  //手动初始化和使用make_shared函数模板初始化有什么区别?
  //开销小,效率高(数据和引用计数存在同一个空间)
  //构造函数初始化:数据和引用计数不再同一段空间,需要间接访问
//常规操作:
  shared_ptr<A> a1 = make_shared<A>();
  shared_ptr<A> a2(a1);
  cout << a2.use_count() << endl;  //返回当前有多少个指针指向当前对象或者空间
  if (a1.unique())  //判断当前指针是否独享(只有它自己指向该对象)或者空间
  {
  cout << "a1 is unique ptr" << endl;
  }
  a1.reset();
  if (a1 == nullptr)  //NULL:void*()   0
  {
  cout << "a1 is nullptr" << endl;
  }
  cout << a2.use_count() << endl;
  //判断当前指针是否独享该对象,如果独享,则释放该对象,并使该指针指向形参所对应的空间
  a1.reset(new A(10));
  //shared_ptr<A> pa(new A(188));
  //a1.reset(pa);
  cout << a1->m_a << endl;
  shared_ptr<int> pd = make_shared<int>(5);
  Test(pd.get());
#endif
  //指定删除器:当删除器不起作用的时候,需要自己指定删除器 void(*)(T*)
  //shared_ptr<A> pa(new A[3]);  //delete pa --->应该是delete []pa;
  //shared_ptr<A[]> pa(new A[3]);
  //shared_ptr<A> pa(new A[3], Mydelete);
  //shared_ptr<A> pa(new A[3], default_delete<A[]>());
  /*shared_ptr<A> pa(new A[3], [](A*a) {
  delete[]a;    //lambda表达式
  });*/
  shared_ptr<A> pa(new A(5));
  const shared_ptr<A> &rpa = move(pa);
  //shared_ptr<A> &&rpa = move(pa);
  cout << "***************"<<endl;
  //pa = nullptr;
  cout << pa.use_count() << endl;
  cout << rpa.use_count() << endl;
  return 0;
}


1.3 auto_ptr


#include <iostream>
#include <memory>
using namespace std;
class Test 
{
public:
  Test()
  {
  cout << "Test的构造函数" << endl;
  }
  void print()
  {
  cout << "hello world" << endl;
  }
  ~Test()
  {
  cout <<"Test的析构函数"<<endl;
  }
};
void func1()
{
  Test *pt = new Test;
}
void func2()
{
  auto_ptr<Test> pt(new Test);
  pt->print();  //pt.operator->(print());
}
int main(void)
{
  func2();
  func2();
}


1.4 weak_ptr


1.4.1 概念


弱指针:不会控制对象的生命周期(不会改变对象的引用计数)。
share_ptr释放指向对象时,是不会考虑weak_ptr是否指向该对象。
weak_ptr不是独立指针,不能单独操作所指向的资源。


1.4.2 作用


weak_ptr指针一般用来辅助share_ptr的使用(监视share_ptr指向对象的生命周期)
weak_ptr和share_ptr可以相互转化,share_ptr可以直接赋值给weak_ptr
但是反过来是行不通的,需要使用lock函数。


1.4.3 常规操作


(1)lock函数

调用Lock函数用来获取share_ptr(如果对象已经被释放,则返回一个空的share_ptr)


shared_ptr<A> pa(new A(5));
pa.reset();
weak_ptr<A> wpa = pa;
auto pb = wpa.lock();  //将弱指针转为共享指针
if(nullptr == pb)
{
    cout << "pb is nullptr" << endl;
}
else
{
    cout << "pb is not nullptr" << endl;
}


(2)use_count

功能:返回有多少个weak_ptr智能指针指向对象(引用计数的个数)
用途:主要用于调试。


(3)expired

功能:判断弱指针是否过期(所检测的对象是否被释放 true /false)


//wpa.reset();  //弱引用计数-1,
cout << wpa.use_count() << endl;  //返回的是weak_ptr的引用计数
cout << pb.use_count() << endl;
if (wpa.expired())    //判断当前弱指针指向的对象是否被释放,弱被释放,返回true,否则返回false
{
    cout << "wpa poniter class is free" << endl;
}


(4) 循环引用

#include <iostream>
#include <memory>
#include <string>
using namespace std;
class Child;
class Parent;
class A
{
public:
  A()
  {
  cout << "A的无参构造" << endl;
  }
  A(int n)
  {
  m_a = n;
  cout << "A的有参构造" << endl;
  }
  ~A()
  {
  cout << "A的析构函数" << endl;
  }
public:
  int m_a;
};
class Parent
{
public: 
  Parent()
  {
  cout << "Parent的构造函数" << endl;
  }
  ~Parent()
  {
  cout << "parent的析构函数" << endl;
  }
  weak_ptr<Child> c;
};
class Child :public Parent
{
public:
  Child()
  {
  cout << "Child的构造函数" << endl;
  }
  ~Child()
  {
  cout << "Child的析构函数" << endl;
  }
  weak_ptr<Parent> p;
};
int main(void)
{
#if 0
  //weak_ptr<A> wpa(new A(5));  //不能独立操作一块空间
  shared_ptr<A> pa(new A(5));
  //weak_ptr:类模板,弱指针(弱引用计数)
  weak_ptr<A> wpa = pa; 
  weak_ptr<A> wpb = pa;
  weak_ptr<A> wpc = pa;  //弱引用不会影响其生命周期,无论多少个弱引用指向这段空间,只要强引用计数为0,则释放这段空间
  //常规操作:
  shared_ptr<Parent> pp(new Parent);
  shared_ptr<Child> cc(new Child);
  pp->c = cc;
  cc->p = pp;
  cout << "hello world" << endl;
#endif
  shared_ptr<A> pa(new A(5));
  //pa.reset();
  weak_ptr<A> wpa = pa;
  auto pb = wpa.lock();  //将弱指针转为共享指针
  if(nullptr == pb)
  {
  cout << "pb is nullptr" << endl;
  }
  else
  {
  cout << "pb is not nullptr" << endl;
  }
  //wpa.reset();  //弱引用计数-1,
  cout << wpa.use_count() << endl;  //返回的是weak_ptr的引用计数
  cout << pb.use_count() << endl;
  if (wpa.expired())    //判断当前弱指针指向的对象是否被释放,弱被释放,返回true,否则返回false
  {
  cout << "wpa poniter class is free" << endl;
  }
  return 0;
}


(5) share_ptr & weak_ptr

尺寸:share_ptr 和 weak_ptr一样大,都是裸指针的两倍


#include <iostream>
#include <memory>
#include <string>
using namespace std;
class Child;
class Parent;
class A:public enable_shared_from_this<A>
{
public:
  A()
  {
  cout << "A的无参构造" << endl;
  }
  A(int n)
  {
  m_a = n;
  cout << "A的有参构造" << endl;
  }
  //A *GetAddr()
  shared_ptr<A> GetAddr()
  {
  //return this;
  //shared_ptr<A> tmp(this);
  //return tmp;
  //实现原理:
    //其内部有一个weak_ptr类型的成员变量_wptr
    //当shared_ptr构造的时候,如果其模板类型继承了enable_shared_from_this<T>,则堆_wptr进行初始化操作
    //这样在调用shared_from_this()的时候,就能通过weak_ptr构造出对应的shared_ptr
  return shared_from_this();  //和pa共享其所有权
  }
  ~A()
  {
  cout << "A的析构函数" << endl;
  }
public:
  int m_a;
};
class Parent
{
public: 
  Parent()
  {
  cout << "Parent的构造函数" << endl;
  }
  ~Parent()
  {
  cout << "parent的析构函数" << endl;
  }
  weak_ptr<Child> c;
};
class Child :public Parent
{
public:
  Child()
  {
  cout << "Child的构造函数" << endl;
  }
  ~Child()
  {
  cout << "Child的析构函数" << endl;
  }
  weak_ptr<Parent> p;
};
int main(void)
{
#if 0
  //weak_ptr<A> wpa(new A(5));  //不能独立操作一块空间
  shared_ptr<A> pa(new A(5));
  //weak_ptr:类模板,弱指针(弱引用计数)
  weak_ptr<A> wpa = pa; 
  weak_ptr<A> wpb = pa;
  weak_ptr<A> wpc = pa;  //弱引用不会影响其生命周期,无论多少个弱引用指向这段空间,只要强引用计数为0,则释放这段空间
  //常规操作:
  shared_ptr<Parent> pp(new Parent);
  shared_ptr<Child> cc(new Child);
  pp->c = cc;
  cc->p = pp;
  cout << "hello world" << endl;
  shared_ptr<A> pa(new A(5));
  //pa.reset();
  weak_ptr<A> wpa = pa;
  auto pb = wpa.lock();  //将弱指针转为共享指针
  if(nullptr == pb)
  {
  cout << "pb is nullptr" << endl;
  }
  else
  {
  cout << "pb is not nullptr" << endl;
  }
  //wpa.reset();  //弱引用计数-1,
  cout << wpa.use_count() << endl;  //返回的是weak_ptr的引用计数
  cout << pb.use_count() << endl;
  if (wpa.expired())    //判断当前弱指针指向的对象是否被释放,弱被释放,返回true,否则返回false
  {
  cout << "wpa poniter class is free" << endl;
  }
  shared_ptr<int> p(new int(5));
  cout << sizeof(p) << endl;
  cout << sizeof(int *) << endl;
  weak_ptr<int> wp = p;
  cout << sizeof(wp) << endl;
#endif
  //局部对象释放两次,A自己释放一次,share_ptr还会释放一次
  /*A a;
  shared_ptr<A> tmp = a.GetAddr();*/
/*
  shared_ptr<A> GetAddr()
  {
  //return this;
  shared_ptr<A> tmp(this);
  return tmp;
  }
*/
  shared_ptr<A> pa(new A());
  auto tmp = pa->GetAddr();
  cout << pa.use_count() << endl;
  cout << tmp.use_count() << endl;
    int * pt = new int();
  shared_ptr<int> spt1(pt);
  shared_ptr<int> spt2(pt);
  std::cout << "spt1.use_count() = " << spt1.use_count() << std::endl;
  std::cout << "spt2.use_count() = " << spt2.use_count() << std::endl;
  return 0;
}


1.4.4 总结


优点:防止内存泄漏
缺点:造成不必要的开销
相关实践学习
基于阿里云短信服务的防机器人验证
基于阿里云相关产品和服务实现一个手机验证码登录的功能,防止机器人批量注册,服务端采用阿里云ECS服务器,程序语言选用JAVA,服务器软件选用Tomcat,应用服务采用阿里云短信服务,
相关文章
|
6月前
|
开发框架 Linux C语言
C、C++、boost、Qt在嵌入式系统开发中的使用
C、C++、boost、Qt在嵌入式系统开发中的使用
211 1
|
6月前
|
算法 Linux 程序员
嵌入式工程师以及C++程序员到公司就业需要掌握那些技术?
嵌入式工程师以及C++程序员到公司就业需要掌握那些技术?
|
6月前
|
数据处理 C++ UED
如何作为一个嵌入式软件工程师博主获得铁粉:C/C++ 技术分享之道
如何作为一个嵌入式软件工程师博主获得铁粉:C/C++ 技术分享之道
115 0
|
6月前
|
C语言 数据安全/隐私保护 C++
嵌入式中如何把C++代码改写成C语言代码
嵌入式中如何把C++代码改写成C语言代码
75 0
|
6月前
|
存储 缓存 Java
嵌入式系统中C++内存管理基本方法
嵌入式系统中C++内存管理基本方法
135 0
|
6月前
|
存储 编译器 程序员
嵌入式系统中C++基础知识精髓
嵌入式系统中C++基础知识精髓
108 0
|
6月前
|
关系型数据库 数据库 C++
嵌入式数据库sqlite3【基础篇】基本命令操作,小白一看就懂(C/C++)
嵌入式数据库sqlite3【基础篇】基本命令操作,小白一看就懂(C/C++)
|
6月前
|
存储 编译器 C++
嵌入式中C++ 编程习惯与编程要点分析
嵌入式中C++ 编程习惯与编程要点分析
53 1
|
6月前
|
架构师 数据挖掘 程序员
嵌入式系统中C++ 类的设计和实现分析
嵌入式系统中C++ 类的设计和实现分析
72 1
|
6月前
|
算法 小程序 编译器
嵌入式中C++开发的基本操作方法
嵌入式中C++开发的基本操作方法
59 0