C++11/14标准(二)智能指针

c++入门到精通教程 c++11/14/17-王健伟-专题视频课程 本教程适合那些只有一点点c语言编程知识的新手,也适合那些c++98标准已经掌握的不错但对c++11/14/17新标准基本无所知的c++开发老手,欢迎大家尽早加入学习,请大家从授课目录,讲解课程时长、演示范例详尽程度,试听后收获四个方面评估本教程的质量。... 阅读详情

先说一句为什么要用智能指针。智能指针是为了解决内存泄露的问题。C/C++程序员可以自己开辟堆(heap)上的内存空间,同时也需要自己释放堆上的内存空间。一旦忘记释放内存空间,这样会造成内存泄露。

    不得不提及一下RAII机制(资源获取即初始化,Resource Acquisition Is Initialization)。在类的构造函数里面申请资源,然后使用,最后在析构函数中释放资源。所以这也就为什么析构函数需要用virtual来修饰来避免出现内存泄露。

    计算机有栈和堆两种。

    这里提及一点。C++中的对象(class)是指所有的内置型对象(int、float、double等和外置型(用户自定义的对象)对象。一切皆为对象。

如果在栈上创建相应的class,那么OS会自动释放掉相应的内存空间,所以RAII机制工作正常,离开相应的作用域时,class会自动调用自己的析构函数释放资源。但是如果采用new方式在堆上创建class,那么class不会调用自己的析构函数。程序员必须使用delete去销毁它。否则就会造成内存泄露。

    这里再插入两个小知识,我以前面试腾讯外包时被问到的点。

  1. new、delete的机制。

  2. new会抛出异常以及如何让new不抛异常。

    1.new有两个步骤:(1)调用operator new()函数开辟内存空间。(2)调用class的构造函数。

delete也有两个步骤:(1)调用class的析构函数。(2)调用operator delete()释放内存。

    2.new会抛出异常。为了防止抛出异常。就应该使用 std::nothrow。例:

 char *ptr = new(std::nothrow) char [20];

 

    开始介绍智能指针,他们都包含在头文件#include <memory>中。主要解决了部分获取资源自动释放的问题。

  • unique_ptr 

    独占式智能指针,不允许拷贝复制,不允许拷贝构造。它不仅能代理new创建的单个对象,也能够代理new[]创建的对象数组。

    代码如下:

 ///
 /// @file    unique.cpp
 /// @author  kogan(709954896@qq.com)
 /// @date    2020-06-21 09:28:02
 ///
 
#include <iostream>
#include <memory>
#include <utility>
using std::cout;
using std::endl;

int main()
{
  //make_unique在C++11中被遗漏了,在C++14中添加。所以要使用-std=c++14
  
  //创建int型指针。
  //使用工厂方法创建
  std::unique_ptr<int> ptr = std::make_unique<int>(5);
  //也可以初始化时直接创建
  std::unique_ptr<int> ptr2(new int(6));
  
  //std::unique_ptr<int> ptr3(ptr); //不允许拷贝构造
  //std::unique_ptr<int> ptr3 = ptr;//不允许赋值
  
  //创建int型动态数组
  std::unique_ptr<int[]> ptrArray = std::make_unique<int[]>(20);

  cout << "*ptr: " << *ptr << endl;
  //创建出来的unique动态数组,可以使用下表访问。
  ptrArray[2] = 3;
  cout << ptrArray[2] <<  endl;

  //错误用法,能编译成功,但是会出问题。
  //std::unique_ptr<int> ptr5(new int[20]);

  return 0;
}
  • shared_ptr

    引用计数型智能指针。是最有价值、最重要、最有用的组成部分。可以自由地拷贝和赋值。当这个指针指向某个指针时,会引用计数加一。如果是从另外一个smart_ptr那里获取某指针的管理权,则两个smart_ptr指针都会引用计数加一。当引用计数为0时,smart_ptr会删除指针所指向的内存空间。

    代码如下:


 ///
 /// @file    shared.cpp
 /// @author  kogan(709954896@qq.com)
 /// @date    2020-06-21 11:51:39
 ///
 
#include <iostream>
#include <memory>

using std::cout;
using std::endl;

int main()
{
  //初始化方式
  std::shared_ptr<int> ptr(new int(3));
  std::shared_ptr<int> ptr2 = std::make_shared<int>(5);

  //将ptr2管理的指针赋值给ptr3
  std::shared_ptr<int> ptr3(ptr2);
  cout << ptr3.use_count() << endl;
  return 0;
}

面试重点:循环引用计数。

循环引用计数:两个smart_ptr指针互相指向对方,造成内存泄露。此时需要使用weak_ptr。

    代码如下:

  • weak_ptr

弱引用指针。用于观察shared_ptr或weak_ptr。用于解决循环引用计数。因为weak_ptr没有共享资源,它的构造函数不会引起指针引用计数的变化。

 

///
 /// @file    circle_reference.cpp
 /// @author  kogan(709954896@qq.com)
 /// @date    2020-06-21 12:04:48
 ///
 
#include <iostream>
#include <memory>
using std::cout;
using std::endl;
using std::shared_ptr;

class Child;//前置声明
class Parent
{
public:
  Parent(){  cout << "Parent()" << endl;  }
  ~Parent() {  cout << "~Parent()" << endl;  }
  shared_ptr<Child> m_Child;
};

class Child
{
public:
  Child(){  cout << "Child()" << endl;  }
  ~Child(){  cout << "~Child()" << endl;  }
  shared_ptr<Parent> m_Parent;
};

int main(void)
{
  //shared_ptr的循环引用会导致内存泄漏
  shared_ptr<Parent> parent(new Parent);
  shared_ptr<Child> child(new Child);
  
  cout << "sizeof(shared_ptr) = " << sizeof(parent) << endl;
  cout << "parent 's use_count() = " << parent.use_count() << endl;
  cout << "child's use_count() = " << child.use_count() << endl;

  parent->m_Child = child;//赋值
  child->m_Parent = parent;
  cout << "parent 's use_count() = " << parent.use_count() << endl;
  cout << "child's use_count() = " << child.use_count() << endl;

  return 0;
}

使用weak_ptr后不会发生内存泄露。

 

 ///
 /// @file    circle_reference2.cpp
 /// @author  kogan(709954896@qq.com)
 /// @date    2020-06-21 12:09:37
 ///
 
#include <iostream>
#include <memory>
using std::cout;
using std::endl;
using std::shared_ptr;
using std::weak_ptr;

class Child;//前置声明
class Parent
{
public:
  Parent(){  cout << "Parent()" << endl;  }
  ~Parent() {  cout << "~Parent()" << endl;  }
  shared_ptr<Child> m_Child;
};

class Child
{
public:
  Child(){  cout << "Child()" << endl;  }
  ~Child(){  cout << "~Child()" << endl;  }
  //shared_ptr<Parent> m_Parent;
  weak_ptr<Parent> m_Parent;
};

int main(void)
{
  //shared_ptr的循环引用会导致内存泄漏
  //
  //解决方案是将其中一个指针设置为weak_ptr
  //weak_ptr做赋值操作的时候,不会改变引用计数的值
  shared_ptr<Parent> parent(new Parent);
  shared_ptr<Child> child(new Child);
  cout << "sizeof(shared_ptr) = " << sizeof(parent) << endl;
  cout << "parent 's use_count() = " << parent.use_count() << endl;
  cout << "child's use_count() = " << child.use_count() << endl;

  parent->m_Child = child;//赋值
  child->m_Parent = parent;// weak_ptr = shared_ptr;
  cout << endl << "执行赋值之后:" << endl;
  cout << "parent 's use_count() = " << parent.use_count() << endl;
  cout << "child's use_count() = " << child.use_count() << endl;

  return 0;
}

 另一种循环引用计数:


closs node
{
public:
  typedef shared_ptr<Node> ptr_type;
  ptr_type next;
};

auto p1 = make_shared_ptr<Node>();
auto p2 = make_shared_ptr<Node>();

weak的lock函数,在某个作用于内使用lock()会返回一个shared_ptr。

该对象可以操作weak_ptr所指向的shared_ptr。

 

 ///
 /// @file    shared.cpp
 /// @author  kogan(709954896@qq.com)
 /// @date    2020-06-21 11:51:39
 ///
 
#include <iostream>
#include <memory>

using std::cout;
using std::endl;

int main()
{
  //初始化方式
  std::shared_ptr<int> ptr(new int(3));
  std::shared_ptr<int> ptr2 = std::make_shared<int>(5);

  //将ptr2管理的指针赋值给ptr3
  std::shared_ptr<int> ptr3(ptr2);
  cout << "reference count: " <<  ptr3.use_count() << endl;

  std::weak_ptr<int> wptr(ptr);
  cout << "reference count: " <<  ptr3.use_count() << endl;
  {
    cout << "*ptr: " << *ptr << endl;
    std::weak_ptr<int> wptr(ptr);
    auto sp = wptr.lock();
    (*sp) = 5;
    cout << "*ptr: " << *ptr << endl;
  }
  cout << "*ptr: " << *ptr << endl;

  return 0;
}

 

c++ 智能指针示例 总结 很多理论介绍的很好了,但看了后还是难以下手。 有时候实际的例子更有代入感,本文主要介绍项目中实际的智能指针应用例子。 一 局部函数中使用 几乎所有资料,介绍的都是智能指针在局部函数中的使用 0)直接定义方式 整形智能指针 unique_ptr<uint8_t> bits(new uint8_t[size.cx * size.cy * 4])......... 阅读详情

相关推荐

嘉立创EDA实战:从点亮第一盏灯到完成首块PCB

本文详细介绍了使用嘉立创EDA从点亮第一盏LED灯到完成首块PCB的全过程。通过实战案例分享,包括原理图绘制、PCB设计、DRC检查、覆铜操作等关键步骤,帮助电子设计爱好者快速掌握嘉立创EDA的使用技巧,并避免常见的设计错误。

weixin_30314793的博客 373

14.C++中的智能指针

创建aPtr和bPtr时,各自的引用计数会变成1,接着2个赋值语句,又把各自的引用计数加了1,就都变成了2,然后离开作用域,会减1,这样各自的引用计数还保持1,这样就无法释放内存空间,就不会去执行A和B的析构函数。智能指针与常规指针行为类似,但两者的重要区别是智能指针能自动释放他所指向的内存。返回了指向智能指针管理对象的内置指针,提供这个函数,主要是为了向不能使用智能指针的代码中传递一个内置指针。因此,在创建智能指针的时候,必须提供指针可以指向的类型。的引用计数本身是安全无锁的,但对象的读写不是,

机器人视觉感知 1478

ADS负载牵引仿真避坑指南:从零开始搞定Loadpull模板设置

本文是一份针对ADS负载牵引仿真的深度避坑指南,详细解析了Loadpull模板从初始化配置到结果解读的全过程。文章重点阐述了如何根据设计目标灵活设置扫描圆、采样点等关键参数,以解决仿真不收敛、结果不完整等常见问题,并指导读者在功率与效率之间做出理性权衡,最终提取出用于匹配网络设计的最优负载阻抗。

weixin_29234423的博客 597

c++11 之模板定义别名(using)

C++11标准中可以为模板定义别名,比如 template&lt;typename T&gt; using ptr=std::shared_ptr&lt;T&gt;; //这里模板定义ptr&lt;T&gt;为智能指针std::shared_ptr&lt;T&gt;定义的别名 所以实际应用中可以借此来简化代码,比如 #include&lt;memory&gt; #include&lt;s...

AplusX 1306

ubuntu17.04 UHD 驱动出错

ubuntu 17.04 源码安装UHD

xrh003的博客 1万+

未隔离电源设备使用usb转串口调试导致串口模块爆炸烧坏事故记录

这个事就发生在前两天,我们公司的wifi模块被客户用到了咖啡机上,客户寄了一台整机给我们协助调试,还送了几包咖啡豆,本想着还能打个咖啡喝一喝的,但就在咖啡机刚寄过来第一天,就出事了。而这个事故的发生,竟然仅仅是因为同事接了个串口模块到电脑调试打印导致的。谁也想不到,这个3.3V的供电的wifi模块居然还有这么大的威力。直接将usb转TTL串口模块的转换芯片给爆开了,咖啡机也给弄坏了,据同事描述当时情况就只见到一片火光和一声巨响,状况比较惨烈,所幸的是笔记本电脑没有烧坏,但是直接给崩蓝屏了。 ...

fangye945a的博客 6192

c++ 前置声明和智能指针使用的注意事项

但是有一些情况不可以使用前置声明,特别是在需要使用完整的类型的情况,而智能指针则属于这种情况。这篇文章讲了为什么要使用前置声明(主要是加速编译)

dhsjna的博客 423

手把手教你编写PCIe设备驱动:基于Linux内核的实战教程

本文详细介绍了基于Linux内核的PCIe设备驱动开发全流程,包括环境准备、设备探测、中断处理、DMA配置等核心内容。通过实战代码示例和Makefile编写指南,帮助开发者快速掌握PCIe驱动开发技术,实现高性能设备驱动开发与优化。

weixin_30687051的博客 193

c++ 智能指针用法详解

c++ 智能指针用法详解本文介绍c++里面的四个智能指针: auto_ptr, shared_ptr, weak_ptr, unique_ptr 其中后三个是c++11支持,并且第一个已经被c++11弃用。为什么要使用智能指针:我们知道c++的内存管理是让很多人头疼的事,当我们写一个new语句时,一般就会立即把delete语句直接也写了,但是我们不能避免程序还未执行到delete时就跳转了或者在函...

TuxedoLinux的博客 467

三维点云转深度图

点云投影过程是将三维点云数据转化为二维图像坐标的关键步骤,它的实现涉及到相机内外参数的计算,包括相机的内部参数(如焦距和主点)和外部参数(如相机位置和方向)。具体来说,可以通过将每个点的三维坐标转换为相机坐标系下的坐标,然后使用相机内部参数和外部参数来计算在二维图像中的坐标。接着计算每个点的深度值,将深度值映射到像素值上,最后创建深度图像并将深度值赋给对应的像素值。这里需要注意的是,在将深度值映射到像素值上时,需要将像素值转换为 uchar 类型,否则在将深度值赋给像素值时会出现类型不匹配的错误。

点云兔子的博客 3171

[系统安全] 一.什么是逆向分析、逆向分析基础及经典扫雷游戏逆向

娜璋AI安全之家于2020年8月18日开通,将专注于Python和安全技术,主要分享Web渗透、系统安全、CVE复现、威胁情报分析、人工智能、大数据分析、恶意代码检测等文章。真心想把自己近十年的所学所做所感分享出来,与大家一起进步。 系统安全系列作者将深入研究恶意样本分析、逆向分析、攻防实战等,通过在线笔记和实践操作的形式分享与博友们学习,希望能与您一起进步。第一篇文章先带领大家学习什么是逆向分析,然后详细讲解逆向分析的典型应用,接着通过OllyDbg工具逆向分析经典的游戏扫雷,再通过Cheat Engin

杨秀璋的专栏 2万+

前向声明 智能指针_C++11/14标准(二)智能指针

先说一句为什么要用智能指针。智能指针是为了解决内存泄露的问题。C/C++程序员可以自己开辟堆(heap)上的内存空间,同时也需要自己释放堆上的内存空间。一旦忘记释放内存空间,这样会造成内存泄露。 不得不提及一下RAII机制(资源获取即初始化,Resource Acquisition Is Initialization)。在类的构造函数里面申请资源,然后使用,最后在析构函数中...

weixin_39612122的博客 267

【YOLO系列】YOLOv4详解:模型结构、损失函数、训练方法及代码实现

摘要:YOLOv4在目标检测领域实现了精度与速度的平衡,通过CSPDarknet53骨干网络、SPP+PANet特征融合及CIoU损失函数等创新,在MS COCO数据集达到65.7% AP50,V100显卡实现62FPS实时检测。核心优化包括Mosaic数据增强、自对抗训练和解耦头结构,显著提升小目标检测和遮挡场景鲁棒性。代码实现采用CSP模块和SPP多尺度池化,兼顾计算效率与检测性能,为工业落地提供高效解决方案。(149字)

一碗白开水一 1358

C++11及C++14标准的智能指针

智能指针这个概念经常会碰见,而且面试的时候太经常会被问到了,特来总结一下。 C++11的智能指针及其背景 auto_ptr的坑点 C++11之前的智能指针是auto_ptr,一开始它的出现是为了解决指针没有释放导致的内存泄漏。比如忘了释放或者在释放之前,程序throw出错误,导致没有释放。所以auto_ptr在这个对象声明周期结束之后,自动调用其析构函数释放掉内存。 int t =

haolexiao的专栏 1万+

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

现代 C++ 特性(C++11/14/17/20)

特性类型C++11C++14C++17C++20类型推导autoLambda基础 lambda泛型 lambda捕获增强模板 lambda智能指针引入并发与异步thread协程模板编程右值引用折叠表达式Concepts文件与字符串span错误处理try-catch编译期计算constexpr更强更强几乎所有语法都支持。

強雲的博客 1509

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

【C++11、C++14、C++17、C++20新特性整理总结】

C++11、C++14、C++17、C++20新特性整理总结。提示:自用学习一下C++11、C++14、C++17、C++20新特性。

weixin_48629311的博客 5291

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

现代C++语言(C++11/14/17)特性总结和使用建议

C++语言在历史上经过了很多次的演进。最早的时候,C++语言没有模板、STL、异常等特性,之后加入这些特性形成大多数人所熟悉的C++98/03标准。在此之后,C++经过10多年又孕育出了拥有众多革命性变化的C++11标准(在标准正式发布前,被称为C++0x)。C++11包括了约140个新特性和约600个缺陷的修正。由于其变化实在太大,被很多人称为“现代C++语言”(Modern C++ Language),以和之前的经典C++语言作区分。在C++11后,标准委员会又发布了C++14和C++17标准,其内容大

bigchen 7086

C++ 11/14/17/20 新特性大汇总:从 Lambda 到协程的应用

C++ 作为一种广泛应用于系统开发、游戏编程、嵌入式系统等领域的编程语言,其标准的不断演进为开发者带来了更强大、高效且灵活的编程工具。自 C++11 起,C++ 标准委员会相继推出了 C++14、C++17 和 C++20,引入了大量新特性,极大地提升了开发效率和代码质量。本文将对 C++11 到 C++20 的核心新特性进行详细汇总,并结合实际应用场景,探讨从 Lambda 表达式到协程等特性的具体用法。

数字魔方操控师的博客 1345

C++11/14/17新增特性介绍

摘要:C++11/14/17是现代C++的核心版本

优快云_RTKLIB的博客 1352

如何快速掌握C++11/14/17/20:Modern-CPP-Programming课程深度解析

Modern C++ Programming课程是一个面向C和面向对象编程基础学习者的开源课程,旨在帮助学习者掌握C++11/14/17/20等现代标准的编程知识,达到熟练的C++编程水平。该课程涵盖了C++编程的基础知识以及高级语义和概念,是快速提升C++技能的优质资源。 [![C++ logo](https://raw.gitcode.com/gh_mirrors/mo/Modern-CPP

gitblog_00549的博客 1086

C++11新标准

C++11新标准: 目录:C++11新标准:1. C++11有哪些新特性?2. auto,decltype和decltype(auto)的用法:2.1 auto:2.2 decltype:2.3 decltype(auto):3. C++中NULL和nullptr区别:4. 智能指针的原理,常用的智能指针及实现:5. 了解的一些关于lambda函数的知识:6. 智能指针的作用:7. auto_ptr作用:8. 智能指针的循环引用:9. 手写实现智能指针类需要实现哪些函数?10. 智能指针出现循环引用怎么解决

NingHai's blog 1859

C++标准详细介绍:C++11/C++14/C++17

C++11标准引入了多项核心语言特性和标准库改进,显著提升了编程效率和性能。核心特性包括自动类型推导(auto)、范围for循环、nullptr空指针、using类型别名、Lambda表达式、移动语义、override/final关键字、静态断言(static_assert)等。标准库方面新增了智能指针(unique_ptr/shared_ptr)、并发支持(thread/mutex/async/future)、正则表达式、元组(tuple)、哈希容器(unordered_map/set)、固定数组(arr

qq_42279379的博客 668

C++学习(十)(标准,C++11 和 C++14,C++17,C++20)

这段代码像**“智能厨房点单”**——主线程下单后继续干活,协程默默计时处理,最后交付结果,高效利用等待时间!🕒👨🍳和 关键字。

solomonzw的博客 2041

CPP标准

‌C++标准‌是C++编程语言的规范,由国际标准化组织(ISO)制定。C++标准的发展历程可以追溯到1998年,当时ISO/IEC 14882:1998标准被发布,这被认为是第一个C++标准,常被称为C++98。随后,C++标准经历了多次更新和修订,包括C++03(2003年)、C++11(2011年)、C++14(2014年)和C++17(2017年)。

没有手牌的博客 1401

【C++11】智能指针的使用

C++11智能指针的使用,带你领略智能指针浩瀚的世界

有梦想的电信狗 1282

学懂C++(六十):C++ 11、C++ 14、C++ 17、C++ 20新特性大总结(万字详解大全)

C++ 11、C++ 14、C++ 17、C++ 20新特性总结(万字详解大全)

编程技术探索者,分享C/C++、C#、Java、数据库等开发经验,聚焦实战技巧与AI兴趣,助力编程爱好者成长。 4807
上一篇: C++11/14标准(一)左值与右值
下一篇: 在华为外包的工作体验
Koganlee
博客等级 码龄9年 16粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值