C++高频知识点(十)

文章目录

  • 46. 智能指针是什么?怎么使用?
    • 1. std::unique_ptr
    • 2. std::shared_ptr
    • 3. std::weak_ptr
  • 47. 什么是野指针?
    • 1. 使用已释放的指针
    • 2. 未初始化的指针
    • 3. 指针超出作用域
    • 如何避免野指针
      • 1. 立即将指针置空
      • 2. 初始化指针
      • 3. 使用智能指针
      • 4. 避免返回局部变量的地址
  • 48. 虚函数的机制是怎么实现的?
    • 机制实现步骤
  • 49. nullptr和null的区别?
  • 50. 什么是二叉搜索树?实际应用有什么?

46. 智能指针是什么?怎么使用?

C++11标准库引入了三种主要的智能指针:std::unique_ptr、std::shared_ptr和std::weak_ptr。

1. std::unique_ptr

std::unique_ptr是一个独占所有权的智能指针,它确保同一时间内只有一个指针可以拥有某个对象的所有权。适合用于一个对象只能被一个指针拥有的情况。

#include <iostream>
#include <memory>class MyClass {
public:MyClass() {std::cout << "MyClass Constructor" << std::endl;}~MyClass() {std::cout << "MyClass Destructor" << std::endl;}void display() {std::cout << "Display method of MyClass" << std::endl;}
};int main() {// 创建一个unique_ptr对象,管理MyClass实例std::unique_ptr<MyClass> ptr1(new MyClass());ptr1->display(); // 使用智能指针调用方法// 转移所有权std::unique_ptr<MyClass> ptr2 = std::move(ptr1);if (!ptr1) {std::cout << "ptr1 is now null" << std::endl;}ptr2->display(); // 使用新的智能指针调用方法// ptr2超出作用域,MyClass对象自动销毁return 0;
}

在这里插入图片描述

2. std::shared_ptr

std::shared_ptr是一个共享所有权的智能指针,可以被多个指针共享。它通过引用计数来管理对象的生命周期,当最后一个std::shared_ptr销毁时,对象才会被释放。

#include <iostream>
#include <memory>class MyClass {
public:MyClass() {std::cout << "MyClass Constructor" << std::endl;}~MyClass() {std::cout << "MyClass Destructor" << std::endl;}void display() {std::cout << "Display method of MyClass" << std::endl;}
};int main() {// 创建一个shared_ptr对象,管理MyClass实例std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();{// 创建第二个shared_ptr,共享相同的对象std::shared_ptr<MyClass> ptr2 = ptr1;ptr2->display(); // 使用智能指针调用方法std::cout << "ptr2 going out of scope" << std::endl;} // ptr2超出作用域,但对象未销毁,因为ptr1还在使用ptr1->display(); // 使用剩余的智能指针调用方法// ptr1超出作用域,MyClass对象自动销毁return 0;
}

在这里插入图片描述

3. std::weak_ptr

std::weak_ptr是一个不拥有所有权的智能指针,它是为了配合std::shared_ptr使用,解决循环引用问题std::weak_ptr不能直接访问对象,需要先转换为std::shared_ptr。

#include <iostream>
#include <memory>class MyClass {
public:std::shared_ptr<MyClass> other;MyClass() {std::cout << "MyClass Constructor" << std::endl;}~MyClass() {std::cout << "MyClass Destructor" << std::endl;}void display() {std::cout << "Display method of MyClass" << std::endl;}
};int main() {std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();std::shared_ptr<MyClass> ptr2 = std::make_shared<MyClass>();// 使用weak_ptr避免循环引用ptr1->other = ptr2;ptr2->other = ptr1;ptr1->display();ptr2->display();// ptr1和ptr2超出作用域,MyClass对象自动销毁return 0;
}

在这里插入图片描述
如果要使用 std::weak_ptr 来避免循环引用,可以对 MyClass 的 other 成员使用 std::weak_ptr,而不是 std::shared_ptr。这样做可以防止形成循环引用,从而避免对象无法正确释放的问题。下面是修改后的示例代码:

#include <iostream>
#include <memory>class MyClass {
public:std::weak_ptr<MyClass> other;  // 使用 weak_ptr 避免循环引用MyClass() {std::cout << "MyClass Constructor" << std::endl;}~MyClass() {std::cout << "MyClass Destructor" << std::endl;}void display() {std::cout << "Display method of MyClass" << std::endl;}
};int main() {std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();std::shared_ptr<MyClass> ptr2 = std::make_shared<MyClass>();// 使用 weak_ptr 来避免循环引用ptr1->other = ptr2;ptr2->other = ptr1;ptr1->display();ptr2->display();// ptr1 和 ptr2 超出作用域,MyClass 对象会正确释放return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
当然,以下是一个总结 std::unique_ptr、std::shared_ptr 和 std::weak_ptr 三种智能指针特点的表格:

在这里插入图片描述
在这里插入图片描述

47. 什么是野指针?

野指针(Dangling Pointer)是指那些指向已经释放或未分配内存的指针。使用野指针会导致未定义行为,包括程序崩溃、数据损坏等严重问题。

以下是关于野指针的详细说明。

野指针的成因

1. 使用已释放的指针

当一个指针指向的内存被释放后,指针仍然保留原来的地址,此时指针变成野指针。

int* p = new int(10);
delete p;
// 此时,p成为野指针
// *p = 20; // 未定义行为,可能导致程序崩溃

2. 未初始化的指针

未初始化的指针默认指向一个不确定的地址,直接使用这种指针会导致野指针问题。

int* p; // p未初始化,指向一个随机地址
// *p = 10; // 未定义行为,可能导致程序崩溃

3. 指针超出作用域

当指针指向的内存区域超出其作用域后,指针变成野指针。

int* foo() {int x = 10;return &x; // 返回局部变量的地址
}
// int* p = foo(); // p成为野指针,x已超出作用域

如何避免野指针

1. 立即将指针置空

在释放内存后,立即将指针置为空指针(nullptr),避免使用野指针。

int* p = new int(10);
delete p;
p = nullptr; // 避免使用野指针

2. 初始化指针

声明指针时,立即进行初始化。如果不知道该指向哪里,可以将其初始化为nullptr。

int* p = nullptr; // 初始化指针
// *p = 10; // 编译错误,安全

3. 使用智能指针

智能指针(如std::unique_ptr和std::shared_ptr)可以自动管理内存,防止野指针。

#include <memory>void example() {std::unique_ptr<int> p = std::make_unique<int>(10);// 不需要手动释放内存
}

4. 避免返回局部变量的地址

不要返回局部变量的地址,可以使用动态分配或者将结果通过参数返回。

int* foo() {int* x = new int(10); // 动态分配内存return x;
}void foo(int& x) {x = 10; // 通过参数返回
}

48. 虚函数的机制是怎么实现的?

在这里插入图片描述

机制实现步骤

在这里插入图片描述

#include <iostream>class Base {
public:virtual void show() {std::cout << "Base class show function\n";}
};class Derived : public Base {
public:void show() override {std::cout << "Derived class show function\n";}
};int main() {Base* b = new Derived();b->show(); // 将调用Derived类的show函数delete b;return 0;
}

在这里插入图片描述

49. nullptr和null的区别?

在这里插入图片描述
由于NULL是一个整数常量,使用NULL可能导致一些类型不安全的问题。例如:

void foo(int) { std::cout << "int" << std::endl; }
void foo(void*) { std::cout << "void*" << std::endl; }int main() {foo(NULL); // 调用 foo(int),而不是 foo(void*)cout<<NULL<<endl; //这里输出0;return 0;
}

现在编译器能发现问题,但是还是避开写NULL
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

50. 什么是二叉搜索树?实际应用有什么?

在这里插入图片描述
在这里插入图片描述
这种性质使得在BST中查找、插入和删除元素非常高效,平均时间复杂度为 O(log n)。

在这里插入图片描述
6. 自动补全和拼写检查:

  • 使用BST实现字符串的前缀树,用于自动补全和拼写检查。

之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/88826.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/88826.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c#中Random类、DateTime类、String类

C# 中 Random 类分析Random 类用于生成伪随机数&#xff0c;位于 System 命名空间。它的核心机制是基于一个种子值 (seed)&#xff0c;通过算法生成看似随机的数列。相同种子会生成相同的随机数序列&#xff0c;这在需要可重现的随机场景中很有用。核心特点种子与随机性默认构造…

Vscode 下载远程服务器失败解决方法

今天在使用 vscode 连接远程主机时&#xff0c;突然再次遇到这个问题&#xff0c;按照以往的经验&#xff0c;直接按照这个博主的文章其实就能解决&#xff0c;但是不知道为什么&#xff0c;今天这个方案失效了&#xff0c;然后卸载安装服务器和本机的vscode什么的也都试过了&a…

【算法】贪心算法:柠檬水找零C++

文章目录前言题目解析算法原理代码示例策略证明前言 题目的链接&#xff0c;大家可以先试着去做一下再来看一下思路。 860. 柠檬水找零 - 力扣&#xff08;LeetCode&#xff09; 题目解析 首先我们要认真去拿到题目中的关键有用信息。 认真的去阅读题目给的示例&#xff0c;然…

27.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--币种服务(一)

从本篇文章开始&#xff0c;我们将用两篇内容详细介绍币种服务的实现。币种服务本身结构较为简单&#xff0c;核心功能包括内置币种的初始化、币种汇率的同步以及汇率的查询。在本篇中&#xff0c;我们将重点讲解如何实现内置币种的初始化功能&#xff0c;为后续的服务打下基础…

(2)从零开发 Chrome 插件:实现 API 登录与本地存储功能

从零开发 Chrome 插件&#xff1a;实现 API 登录与本地存储功能 Chrome 插件作为浏览器功能的重要扩展&#xff0c;能极大提升用户的工作效率。本文将以一个「登录功能插件」为例&#xff0c;带你从零构建一个可调用 API 验证身份、并将用户信息存储在本地的 Chrome 插件。 基…

Flink时间窗口详解

一、引言在大数据流处理的领域中&#xff0c;Flink 的时间窗口是一项极为关键的技术&#xff0c;想象一下&#xff0c;你要统计一个电商网站每小时的订单数量。由于订单数据是持续不断产生的&#xff0c;这就形成了一个无界数据流。如果没有时间窗口的概念&#xff0c;你就需要…

宽带接入,网线插入电脑的经验

现在一般家里安装移动宽带&#xff0c;都会提供四个千兆接口的光猫路由器&#xff0c;但是要注意了 首先网线的两端看起来一样&#xff0c;实际上并不是&#xff0c;如果发现连接不成功&#xff0c;那么就要换一头重新尝试&#xff0c; 一般像说什么自动DHCP啊&#xff0c;因为…

crmeb多门店对接拉卡拉支付小程序聚合收银台集成全流程详解

一、商户注册与配置​​注册支付平台账号​​&#xff1a;在拉卡拉开放平台注册商户账号&#xff08;私信联系注册&#xff09;​​创建应用​​&#xff1a;获取小程序应用ID(AppID)​​配置支付参数​​&#xff1a;商户号(MID)终端号(TID)API密钥支付回调地址二、配置拉卡拉…

C#将树图节点展示到NetronLight图表中

之前写过NetronLight开源框架 C#使用开源框架NetronLight绘制流程图-CSDN博客 我们这里将TreeView树图的节点内容展示到NetronLight图表中&#xff0c;按照树的层次【深度Level】展示 新建窗体应用程序ShowTreeNodeToDiagram&#xff0c;将默认的Form1重命名为FormShowNode&…

精密模具大深径比微孔尺寸检测方案 —— 激光频率梳 3D 轮廓检测

引言精密模具中大深径比微孔&#xff08;深径比&#xff1e;20:1&#xff0c;孔径&#xff1c;1mm&#xff09;的尺寸精度直接影响注塑件、电子元件等产品的成型质量。此类微孔具有孔径小、深度大、表面质量要求高&#xff08;Ra≤0.1μm&#xff09;等特点&#xff0c;传统检测…

defer学习指南

一、源头&#xff1a;早期管理资源&#xff08;如数据库连接、锁、文件句柄、网络连接&#xff09;和状态清理异常麻烦。 必须在每个可能的返回点&#xff08;return、err、panic&#xff09;手动重复清理代码&#xff0c;极易遗漏且打断主要逻辑思路&#xff01;像Java语言虽然…

NLP_知识图谱_大模型——个人学习记录

1. 自然语言处理、知识图谱、对话系统三大技术研究与应用 https://github.com/lihanghang/NLP-Knowledge-Graph 深度学习-自然语言处理(NLP)-知识图谱&#xff1a;知识图谱构建流程【本体构建、知识抽取&#xff08;实体抽取、 关系抽取、属性抽取&#xff09;、知识表示、知…

linux:进程详解(1)

目录 ​编辑 1.进程基本概念与基本操作 1.1 概念 1.2 描述进程-PCB 1.2.1PCB的基本概念 1.2.2 task_ struct 1.2.3 查看进程 2.进程状态 2.1 Linux内核源码展示 2.2 进程状态查看 ​编辑 2.3 Z(zombie)-僵⼫进程 2.4 僵尸进程的危害 2.5 孤儿进程 3.进程优先级 …

碳中和目标下的全球产业链重构:深度解析与未来路径

引言&#xff1a;气候临界点与产业链的系统性风险2023年&#xff0c;全球平均气温较工业化前上升1.2℃&#xff0c;南极冰盖年消融量达1500亿吨&#xff0c;极端天气事件导致的经济损失占全球GDP的2.3%。这一系列数据背后&#xff0c;暴露出传统产业链的致命缺陷——其设计逻辑…

FPGA实现SDI转LVDS视频发送,基于GTX+OSERDES2原语架构,提供2套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的所有工程源码总目录----方便你快速找到自己喜欢的项目本博已有的 SDI 编解码方案FPGA实现LVDS视频收发方案 3、工程详细设计方案工程设计原理框图SDI 输入设备Gv8601a 均衡器GTX 解串SMPTE SD/HD/3G SDI IP核BT1120转RGB奇…

新手向:使用Python构建高效的日志处理系统

本文将详细讲解如何使用Python开发一个专业的日志分析工具&#xff0c;能够自动化处理、分析和可视化各类日志文件&#xff0c;大幅提升运维效率。环境准备开发本工具需要以下环境配置&#xff1a;Python环境&#xff1a;建议Python 3.8或更高版本必要库&#xff1a;pandas&…

大模型-量化技术

简介 模型量化是一种重要的模型压缩技术。其核心目标是在可控精度损失下&#xff0c;将大模型中浮点型权重&#xff08;通常为 float32 等高精度格式&#xff09;近似转换为低精度离散值表示&#xff08;通常为 int8&#xff09;。 具体而言&#xff0c;该技术通过将模型的权重…

【C语言网络编程】HTTP 客户端请求(域名解析过程)

在做 C 语言网络编程或模拟 HTTP 客户端时&#xff0c;第一步就离不开“把域名解析为 IP 地址”这一步。很多人可能直接复制粘贴一段 gethostbyname 的代码&#xff0c;但未必真正理解它的原理。 本篇博客将围绕一个经典函数&#xff1a; char *host_to_ip(const char *hostna…

Node.js特训专栏-实战进阶:16. RBAC权限模型设计

🔥 欢迎来到 Node.js 实战专栏!在这里,每一行代码都是解锁高性能应用的钥匙,让我们一起开启 Node.js 的奇妙开发之旅! Node.js 特训专栏主页 专栏内容规划详情 我将从RBAC权限模型的基础概念、核心组件讲起,详细阐述其设计原则、数据库模型设计,还会结合代码示例展示在…

mac上BRPC的CMakeLists.txt优化:解决Protobuf路径问题

问题背景与挑战 在构建高性能RPC框架BRPC时&#xff0c;​Protobuf依赖路径的配置往往是开发者面临的主要挑战之一。原始CMake配置在寻找Protobuf库时存在以下痛点&#xff1a; ​路径搜索不精确​&#xff1a;默认find_library无法定位自定义安装路径下的Protobuf​版本兼容…