QT中的 容器(container)-大全

一、介绍

Qt库提供了一套通用的基于模板的容器类,可以用这些类存储指定类型的项。比如,你需要一个大小可变的QString的数组,则使用QVector<QString>。

这些容器类比STL(C++标准模板库)容器设计得更轻量、更安全并且更易于使用。如果对STL不熟悉,或者倾向于用“Qt的方式”,那么你可以使用这些类,而不去使用STL的类。(STL容器使用详见首页其他作品)

二、容器类

Qt提供了一些顺序容器:QList、QLinkedList、QVector、QStack和QQueue。因为这些容器中的数据都是一个接一个线性存储的,所以称为顺序容器。大多数时候,QList是最好的选择,虽然是用数组实现的,但在它的首尾添加元素都非常快。如果你需要一个链表(linked-list)就用QLinkedList;想要你的项在内存中连续存储,就使用QVector。QStack和QQueue(栈和队列)分别提供了后进先出(LIFO)和先进先出(FIFO)的机制。

Qt还提供了一些关联容器:QMap、QMultiMap、QHash、QMultiHash、QSet。因为这些容器存储的是<键,值>对,比如QMap<Key,T>,所以称为关联容器。其中“Multi”容器支持一个键对应多个值。“Hash”容器在有序集合上使用hash函数进行快速的查找,而没有用二叉搜索。

容器也可以嵌套使用,例如QMap<QString,QList<int> >,这里键的类型是QString,而值的类型是QList<int>,需要注意,在后面的“> >”符号之间要有一个 空格,不然编译器会将它当作“>>”操作符对待。

该代码运行环境为Windows,采用Mingw64编译器输出结果。

1. QList容器

QList是一个模板类,提供了一个列表。QList<T>实际上是一个T类型项目的指针数组,所以支持基于索引的访问,而且当项目的数目小于1000时,可以实现在列表中间进行快速的插入操作。

QList提供了很多方便的接口函数来操作列表中的项目,例如插入操作insert()、替换操作replace()、移除操作removeAt()、移动操作move()、交换操作swap()、在表尾添加项目append()、在表头添加项目prepend()、从列表中移除一项并获取这个项目takeAt()及相应的takeFirst()和takeLast()、获取一个项目的索引indexOf()、判断是否含有相应的项目contains()以及获取一个项目出现的次数count()等。

插入

#include "widget.h"

#include <QApplication>
#include <QList>
#include <QMap>
#include <QSplitter>
#include <QVector2D>
#include <QVector>
#include <QtAlgorithms>
#include <QtCore>
#include <QtWidgets>

void printList(QList<int>&li)
{
    for(auto it = li.begin();it != li.end();it++)
    {
        qDebug()<< *it <<"=\t"<< &(*it);
    }
}

int main(int argc, char* argv[])
{
 QCoreApplication a(argc, argv); //无GUI的窗口

    QList<int> li;
    //插入
    li.insert(li.begin(),1); //在迭代器开始位置插入1
    li.insert(0,2); //在0序号位置插入 2
    li.insert(4,100); //在4序号位置插入 100
    li.append(10); //追加元素10
    li.push_back(3); // 尾插
    li.push_front(3); // 头插
    li.push_back(1);
    li.push_back(1);
    li.push_back(1);
    li.push_back(1);
    li << 20 << 30<<40;
    //替换
    li.replace(0,200);
    printList(li);

    return a.exec();
}

运行结果如下,可以看出QList容器的元素地址分配十分规律,一次偏移8字节 ,存储的应该是指针(不确定)

其他操作

QList<int> li;
    //插入
    li << 20 << 30<<40<< 50<<60 <<30 ;
    //删除
    li.erase(li.begin());
    li.takeAt(0);
    //    li.takeLast();   // 删除最后一个元素
    //    li.takeFirst();  // 删除第一个元素
    //替换
    li.replace(3,200); // 3下标 为第四个
    //统计
    qDebug()<<"count(3) = "<<li.count(30); //统计元素出现的次数
    qDebug()<<"contains 50? = "<< li.contains(50);

 QVector容器

插入

插入和QList容器相比,insert方法插入  li.insert(4,100);  报错:不能够超出索引插入元素。

#include "widget.h"

#include <QApplication>
#include <QList>
#include <QMap>
#include <QSplitter>
#include <QVector2D>
#include <QVector>
#include <QtAlgorithms>
#include <QtCore>
#include <QtWidgets>


void printList(QVector<int>&li)
{
    for(auto it = li.begin();it != li.end();it++)
    {
        qDebug()<< *it <<"=\t"<< &(*it);
    }
}
int main(int argc, char* argv[])
{
 QCoreApplication a(argc, argv); //无GUI的窗口

 QVector<int> li;
    //插入

    li.insert(li.begin(),1); //在迭代器开始位置插入1
    li.insert(0,2); //在0序号位置插入 2
//    li.insert(4,100); //在4序号位置插入 100
    li.append(10); //追加元素10
    li.push_back(3); // 尾插
    li.push_front(3); // 头插
    li.push_back(1);
    li.push_back(1);
    li.push_back(1);
    li.push_back(1);
    li << 20 << 30<<40;
    //替换
    li.replace(0,200);
    printList(li);

    return a.exec();
}

运行结果如下,可以看到内存直接分配的间隔为4字节,比QList小 ,存储的为int的大小

 

其他方法

比QList容器多个capacity 方法,类似与std::vector容器

QLinkedList

QLinkedList 的废弃:从 Qt 6.0 开始,QLinkedList 容器已被废弃并从 Qt 容器库中移除。Qt 团队推荐使用 std::list(C++ 标准库中的双向链表)作为替代

QLinkedList(Qt链表)是一个 C++ 标准库中的双向链表容器类,它是 Qt 框架中的一部分。Qt 框架是一个跨平台的应用程序开发框架,广泛应用于 GUI 和非 GUI 程序的开发。QLinkedList 提供了一个高效的数据结构,用于存储和管理元素的集合。

重要性:

动态大小:QLinkedList 的大小是动态的,可以根据需要轻松添加或删除元素。这使得它在处理具有不确定大小的数据集时非常有用。
双向遍历:与 QVector 和 QList 不同,QLinkedList 允许从头到尾以及从尾到头的双向遍历。这种遍历方式在某些场景下会非常有用。
高效的插入和删除操作:在链表的中间插入或删除元素的时间复杂度为 O(1)。这使得 QLinkedList 在需要频繁插入和删除元素的场景中,具有优势。
不需要连续内存:与 QVector 和 QList 相比,QLinkedList 的元素不需要存储在连续的内存空间中。这意味着在内存碎片化的情况下,QLinkedList 可能更容易分配内存。

QLinkedList 的性能优化

QLinkedList 是 Qt 提供的双向链表容器,适用于需要频繁插入和删除元素的场景。在某些情况下,使用 QLinkedList 可以获得更好的性能。以下是关于 QLinkedList 性能优化的一些建议:

适用场景选择:在需要频繁插入和删除元素的场景下,使用 QLinkedList 是合适的,因为它在这些操作上具有优秀的性能。然而,如果需要频繁地随机访问元素,QList 或 QVector 可能是更好的选择,因为它们提供更快的随机访问速度。
使用迭代器:QLinkedList 提供了迭代器接口,以高效地遍历链表。在需要遍历链表时,使用迭代器可以获得更好的性能。要注意的是,在遍历过程中插入或删除元素时,应使用迭代器的 insert() 和 remove() 函数,以保持链表的完整性。
减少内存分配次数:尽管 QLinkedList 在插入和删除元素时性能优越,但它的内存分配次数相对较多。为了提高性能,可以预先估计链表的大小,并通过 reserve() 函数预留相应的内存空间,以减少内存分配次数。
使用空间局部性:QLinkedList 的元素存储在非连续的内存地址中,这可能导致 CPU 缓存利用率降低。在可能的情况下,尝试让相邻的元素在逻辑上也相邻,以提高空间局部性。
避免频繁拷贝:链表的拷贝操作相对较慢。如果需要共享数据,可以考虑使用 QSharedPointer 进行引用计数,以避免频繁的拷贝操作。
总之,为了充分发挥 QLinkedList 的性能优势,开发者应在合适的场景下使用它,并采用迭代器、预留内存等方法进行优化。同时,也要注意避免在不适合的场景下使用 QLinkedList,以确保整体性能的最优化。

插入

容器的insert插入方法不能指定下标,需要迭代器,且没有replace方法。

template <typename T>
void printList(QLinkedList<T>&li)
{
    for(auto it = li.begin();it != li.end();it++)
    {
        qDebug()<< *it <<"=\t"<< &(*it);
    }

}

int main(int argc, char* argv[])
{
    QCoreApplication a(argc, argv); //无GUI的窗口
    QLinkedList<int> li;
       //插入
       li.insert(li.begin(),1); //在迭代器开始位置插入1
//       li.insert(0,2); //在0序号位置插入 2
//       li.insert(4,100); //在4序号位置插入 100

       li.append(10); //追加元素10
       li.push_back(3); // 尾插
       li.push_front(3); // 头插
       li.push_back(1);
       li.push_back(1);
       li.push_back(1);
       li.push_back(1);
       li << 20 << 30<<40;
       //替换
//       li.replace(0,200);

     printList(li);
    a.exec();
}

结果如下,可以看到元素直接不是顺序存储的,是通过指针链接在一起的,两个相连元素之间大概相差32字节,(因为是双向链表,内存随机分配,每个节点应该包含了 int类型4字节和两个指针16字节,再加上内存偏移)

其他操作

    QLinkedList<int> li;
        //插入
        li << 20 << 30<<40<< 50<<60 <<30 ;
        //删除

        li.erase(li.begin());
//        li.takeAt(0);
        //    li.takeLast();   // 删除最后一个元素
        //    li.takeFirst();  // 删除第一个元素
        //替换
        //统计
        qDebug()<<"count(3) = "<<li.count(30); //统计元素出现的次数
        qDebug()<<"contains 50? = "<< li.contains(50);
    //访问元素
    li.back();
    li.front();
    QLinkedList<int>::iterator it = std::find(li.begin(),li.end(),30);
    if(it!= li.end())
    {
        qDebug() <<*it;
    }

QStack

QStack(Qt Stack)是一个来自于Qt框架的容器类,类似于C++标准库中的std::stack。QStack容器是一种后进先出(LIFO)的数据结构,即最后一个进入堆栈的元素将最先被移除。QStack继承了QVector,所以它拥有QVector的所有功能,同时提供了堆栈的特定操作。
由于QStack继承自QVector,因此它还具有QVector的所有成员函数,如append()、at()、capacity()、contains()、count()、data()、fill()、indexOf()、insert()、lastIndexOf()、mid()、prepend()、remove()、removeAll()、removeAt()、removeFirst()、removeLast()、replace()、reserve()、resize()、size()、squeeze()、startsWith()、swap()、takeAt()、takeFirst()、takeLast()、value()等。然而,在使用QStack时,最好坚持使用堆栈特定的接口,以保持代码的清晰性和可读性。
 

#include "widget.h"

#include <QApplication>
#include <QList>
#include <QMap>
#include <QSplitter>
#include <QVector2D>
#include <QVector>
#include <QtAlgorithms>
#include <QtCore>
#include <QtWidgets>


template <typename T>
void printList(QStack<T>&li)
{
    for(auto it = li.begin();it != li.end();it++)
    {
        qDebug()<< *it <<"=\t"<< &(*it);
    }

}

int main(int argc, char* argv[])
{
    QCoreApplication a(argc, argv); //无GUI的窗口
    QStack<int>s;
    s.reserve(100); //提前分配内存
    s.size(); //获取数据大小
    s.capacity(); //查看容量大小
    s.push(2);
    s.push(3);
    s.push(4);
    s.push(5);
    s.insert(0,1);
    s.insert(1,4);
    //查看栈顶元素
    s.top();
    //弹出栈顶元素
    s.pop();

    printList(s);
    a.exec();
}

运行结果如下,栈是一种顺序存储的容器,每个元素直接相隔4字节大小。

其他用法

s.toList(); //转为QList容器
    s.toStdVector(); //转为std::vector
    printList(s);
    qDebug()<<"stack size = "<<sizeof(s);

    QList<int>l=s.toList();
    std::vector<int> v=s.toStdVector();
    printList(l);
    qDebug()<<"QStack  size = "<<sizeof(l);
    qDebug()<<"std::vector  size = "<<sizeof(v);
    v.push_back(10);
    qDebug()<<"std::vector  size = "<<sizeof(v);

这里补充下关于QStack容器大小的问题,stack容器里有5个int类型的容器,我们可能以为sizeof的大小的5*4 =20;但是这里却是8字节,转为STL中的容器,可以看到结果如下所示,这些容器的内部会有各自的实现。

QQueue容器

QQueue 是 Qt 库中的一个容器类,它表示一个双端队列(double-ended queue,简称 deque)。QQueue 提供了在队列两端进行高效插入和删除操作的功能。QQueue 继承自 QList,可以在首尾方便地添加和删除元素。下面是一些 QQueue 的使用场景:

任务队列:可以用 QQueue 来管理一个任务队列,将待处理的任务添加到队列中,然后依次处理并移除已完成的任务。这种场景下,可以将 QQueue 当作一个先进先出(FIFO)数据结构来使用。
消息队列:在多线程应用中,可以使用 QQueue 存储线程间通信的消息。主线程将消息添加到队列中,子线程从队列中取出消息并处理。这种场景下,需要确保对队列的访问是线程安全的,可以通过加锁等机制实现。
数据缓冲:在处理大量数据时,可以使用 QQueue 作为缓冲区,存储已经处理过的数据,以便在需要时能够快速访问。例如,在处理实时音频或视频数据时,可以将已处理的数据帧存入 QQueue 中,以备后续的播放或分析使用。
编程算法:QQueue 可以用于实现一些编程算法,如宽度优先搜索(BFS)等。通过将待处理的节点添加到队列中,可以保证算法的执行顺序。
事件处理:在事件驱动的程序中,可以使用 QQueue 存储待处理的事件。当事件发生时,将事件对象添加到队列中,然后逐个处理并删除队列中的事件。

比QVector容器多了enqueue插入元素的方法。

综上所述,QQueue作为一种实用的数据结构,广泛应用于不同领域的软件开发。了解QQueue的重要性和基本概念,将有助于开发者更好地利用这一工具解决实际问题。

QQueue的性能优化


  QQueue 是 Qt 容器类之一,它实现了一个先进先出(FIFO)的队列。QQueue 是 QList 的子类,因此它继承了 QList 的许多特性。为了优化 QQueue 的性能,可以采取以下几个方面的措施:利用 QList 的特性:QQueue 的底层实现基于 QList,所以可以利用 QList 的性能优势。QList 的内存分配策略使得在队列的头部和尾部插入和删除元素具有较高效率。因此,当使用 QQueue 时,尽量避免在队列中间进行插入和删除操作。
预分配内存:如果可以预估队列的最大大小,那么可以使用 QQueue::reserve() 函数预先分配内存。这将有助于减少内存分配和释放的开销,提高性能。
避免频繁的内存分配:在频繁地向队列添加和删除元素时,避免频繁的内存分配和释放。可以考虑使用对象池或其他内存管理技术来重用对象,从而提高性能。
使用 const 成员函数:在遍历队列或访问队列元素时,使用 const 成员函数(如 constFirst() 和 constLast())可以避免不必要的拷贝操作,提高性能。
考虑使用其他容器:在某些特定场景下,QQueue 可能不是性能最优的选择。例如,如果需要处理大量连续内存访问操作,可以考虑使用 QVector。同样,如果需要在列表中间频繁地插入和删除元素,QLinkedList 可能是更好的选择。根据实际需求选择合适的容器类,以实现最佳性能。
总之,在使用 QQueue 时,可以通过充分利用 QList 的特性、预分配内存、避免频繁的内存分配、使用 const 成员函数以及根据需求选择合适的容器类等方法来优化性能。

插入

#include "widget.h"

#include <QApplication>
#include <QList>
#include <stack>
#include <queue>
#include <map>
#include <QMap>
#include <QSplitter>
#include <QVector2D>
#include <QVector>
#include <QtAlgorithms>
#include <QtCore>
#include <QtWidgets>
#include <vector>

template <typename T>
void printList(QList<T>&li)
{
    for(auto it = li.begin();it != li.end();it++)
    {
        qDebug()<< *it <<"=\t"<< &(*it);
    }

}

template <typename T>
void printList(QQueue<T>&li)
{
    for(auto it = li.begin();it != li.end();it++)
    {
        qDebug()<< *it <<"=\t"<< &(*it);
    }

}

int main(int argc, char* argv[])
{
    QCoreApplication a(argc, argv); //无GUI的窗口
    QQueue<int>li;
    li.enqueue(2);
    li.enqueue(3);
    li.insert(0,1);

    li << 20 << 30<<40;
    //替换
    li.replace(0,200);
    qDebug()<<"head = "<<li.head();
    qDebug()<<"take = "<<li.takeAt(3); //删除元素返回元素值
    li.dequeue(); //出队列


    printList(li);

    a.exec();
}

可以看到 QQueue是一个顺序存储的容器,每个元素之间的间隔为8个字节同QList(继承关系)

​​​​​​​

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

i已学赋能智慧教育时代的幼儿教育

伴随“教育数字化战略行动”的深入开展,智慧教育正式成为国家战略。智慧教育延伸至家校社教育的每个阶段。当前,为适应智慧教育发展趋势,我国制定了《中国教育现代化2035》《教育部关于加强“三个课堂”应用的指导意见》《教育信息化2.0行动计划》等文件。幼儿作为智慧教育、智…

Blazor Select 实现点击一次选项触发一次后台事件

Blazor的官方案例中&#xff0c;Select组件只有两个事件 1、OnSelectedItemChanged 每次选项的时候改变触发&#xff0c;如果你点击同一个选项是不会触发后台的方法的 2、OnBeforeSelectedItemChange 我们可以用这个事件实现每次点击同一个选项都可以触发后台事件 需要注意下最…

OCR文字识别工具 Cisdem OCRWizard激活最新 for Mac

为了提高内容识别的准确性&#xff0c;Cisdem OCRWizard提供供您选择两种模式&#xff1a;文件或名片。此外&#xff0c;它会自动分析的内容&#xff0c;标志着不同颜色的页面上几个区域根据给定部分的性质&#xff1a;文本&#xff08;绿色标记&#xff09;&#xff0c;图像&a…

Stable Diffusion绘画系列【3】:二次元动漫画风

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

单片机BootLoader是咋回事?

BootLoader的定义&#xff1a; CPU进入APP之前运行的一小段程序代码就叫做BootLoader。它是由程序员编写的&#xff0c;作用是更新应用程序。这也就说明了只有BootLoader的单片机才可以升级。有的产品有升级的需要就需要BootLoader了。 单片机的启动过程可以这么叙述&#xff…

ArrayList源码全面解析

一、概述 ArrayList 是 java 集合框架中比较常用的数据结构,继承自 AbstractList&#xff0c;实现了 List 接口。底层采用数组来实现。ArrayList 实现了java.io.Serializable接口&#xff0c;这意味着ArrayList支持序列化&#xff0c;能通过序列化去传输。 1.1、底层数据结构…

fiddler设置手机端抓包看这篇文章就足够了,轻松解决!

fiddler设置手机端抓包 安卓手机抓包 第一步&#xff1a;配置电脑和安卓的相关设置 1、手机和fiddler位于同一个局域网内&#xff1b;首先从fiddler处获取到ip地址和端口号&#xff1a; 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; &#xff0c;点…

10年资深码农,聊聊程序员的35岁危机

程序员的一天&#xff0c;日常都在做什么&#xff1f; 很多外行以及初入 IT 行业的从业者&#xff0c;往往只看到了高薪、加班、敲代码的标签&#xff0c;那程序员的日常究竟是什么样的&#xff1f; 当代程序员的一天&#xff1a;聊天、开会、写代码 哪种技术最热门与能拿到高…

Shell编程基础 – for循环

Shell编程基础 – for循环 Shell Scripting Essentials - for Loop 大多数编程语言都有循环的概念和语句。如果想重复一个任务数十次&#xff0c;无论是输入数十次&#xff0c;还是输出数十次&#xff0c;对用户来说都不现实。 因此&#xff0c;我们考虑如何用好Bash Shell编…

(Spring学习06)Spring之循环依赖底层源码解析

什么是循环依赖&#xff1f; 很简单&#xff0c;就是A对象依赖了B对象&#xff0c;B对象依赖了A对象。 比如&#xff1a; // A依赖了B class A{public B b; }// B依赖了A class B{public A a; }那么循环依赖是个问题吗&#xff1f; 如果不考虑Spring&#xff0c;循环依赖并不…

浅谈STL中的分配器

分配器是STL中的六大部件之一&#xff0c;是各大容器能正常运作的关键&#xff0c;但是对于用户而言确是透明的&#xff0c;它似乎更像是一个幕后英雄&#xff0c;永远也不会走到舞台上来&#xff0c;观众几乎看不到它的身影&#xff0c;但是它又如此的重要。作为用户&#xff…

计算机缺少vcruntime140_1.dll的5个解决方法,轻松解决dll缺失问题

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“缺少vcruntime140_1.dll”。这个错误提示通常出现在运行某些程序或游戏时&#xff0c;这个错误通常会导致某些应用程序无法正常运行。那么&#xff0c;如何解决缺少vcruntime140_1.dll的问…

Vue框架学习笔记——事件处理:v-on指令+methods

文章目录 前文提要事件处理的解析过程&#xff0c;v-on:事件名样例代码如下&#xff1a;效果展示图片&#xff1a;v-on:事件名"响应函数"v-on简写形式响应函数添加响应函数传参占位符"$event"注意事项 前文提要 本人仅做个人学习记录&#xff0c;如有错误…

深度学习框架配置

目录 1. 配置cuda环境 1.1. 安装cuda和cudnn 1.1.1. 显卡驱动配置 1.1.2. 下载安装cuda 1.1.3. 下载cudnn&#xff0c;将解压后文件复制到cuda目录下 1.2. 验证是否安装成功 2. 配置conda环境 2.1. 安装anaconda 2.2. conda换源 2.3. 创建conda环境 2.4. pip换源 3.…

Linux以nohup方式运行jar包

1、在需要运行的jar包同级目录下建立启动脚本文件&#xff1a; 文件内容&#xff1a; #! /bin/bash #注意&#xff1a;必须有&让其后台执行&#xff0c;否则没有pid生成 jar包路径为绝对路径 nohup java -jar /usr/local/testDemo/jdkDemo-0.0.1-SNAPSHOT.jar >/us…

MX6ULL学习笔记 (一)交叉工具链的安装

前言&#xff1a; ARM 裸机、Uboot 移植、Linux 移植这些都需要在 Ubuntu 下进行编译&#xff0c;编译就需要编译 器&#xff0c;Ubuntu 自带的 gcc 编译器是针对 X86 架构的&#xff01;而我们现在要编译的是 ARM 架构的代码&#xff0c;因为我们编译的代码是需要烧写到ARM板子…

nacos集群开箱搭建-linux版本搭建

原创/朱季谦 nacos是一款易于构建云原生应用的动态服务发现、配置管理和服务管理平台&#xff0c;简单而言&#xff0c;它可以实现类似zookeeper做注册中心的功能&#xff0c;也就是可以在springcloud领域替代Eureka、consul等角色&#xff0c;同时&#xff0c;还可以充当spri…

吴恩达《机器学习》10-6-10-7:学习曲线、决定下一步做什么

一、学习曲线 1. 学习曲线概述 学习曲线将训练集误差和交叉验证集误差作为训练集实例数量&#xff08;m&#xff09;的函数绘制而成。这意味着从较少的数据开始&#xff0c;逐渐增加训练集的实例数量。该方法的核心思想在于&#xff0c;当训练较少数据时&#xff0c;模型可能…

MVVM 模式与 MVC 模式:构建高效应用的选择

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

3.2 Windows驱动开发:内核CR3切换读写内存

CR3是一种控制寄存器&#xff0c;它是CPU中的一个专用寄存器&#xff0c;用于存储当前进程的页目录表的物理地址。在x86体系结构中&#xff0c;虚拟地址的翻译过程需要借助页表来完成。页表是由页目录表和页表组成的&#xff0c;页目录表存储了页表的物理地址&#xff0c;而页表…