当前位置: 首页 > news >正文

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.lryc.cn/news/587456.html

相关文章:

  • Excalidraw:一款颠覆传统思维的免费开源绘图工具
  • 什么是RAG(Retrieval-Augmented Generation)?一文读懂检索增强生成
  • Vue3 实现文件上传功能
  • 【操作系统】strace 跟踪系统调用(一)
  • 网络编程 JAVA
  • 2025年渗透测试面试题总结-2025年HW(护网面试) 45(题目+回答)
  • 学习开发之无参与有参
  • 前四天综合总结
  • Cursor的使用
  • ARC 03 从Github Action job 到 runner pod
  • 暑期自学嵌入式——Day01(C语言阶段)
  • BERT系列模型
  • Spring AI 项目实战(十六):Spring Boot + AI + 通义万相图像生成工具全栈项目实战(附完整源码)
  • 闲庭信步使用图像验证平台加速FPGA的开发:第十三课——图像浮雕效果的FPGA实现
  • 【Mysql作业】
  • 16.使用ResNet网络进行Fashion-Mnist分类
  • [GWCTF 2019]我有一个数据库
  • 在 Ubuntu 下安装 MySQL 数据库
  • 谷歌推出Vertex AI Memory Bank:为AI智能体带来持久记忆,支持连续对话
  • 【echarts踩坑记录】为什么第二个Y轴最大值不整洁
  • 华为HarmonyOS 5.0深度解析:跨设备算力池技术白皮书(2025全场景智慧中枢)
  • JavaScript加强篇——第八章 高效渲染与正则表达式
  • vue防内存泄漏和性能优化浅解
  • PHP语法高级篇(二):文件处理
  • 小架构step系列13:测试用例的加载
  • python的平安驾校管理系统
  • C# 接口(接口可以继承接口)
  • MySQL SQL语句精要:DDL、DML与DCL的深度探究
  • 大模型-量化技术
  • mmap映射文件