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

JavaScript系列(50)--编译器实现详解

JavaScript编译器实现详解 🔨

今天,让我们深入探讨JavaScript编译器的实现。编译器是一个将源代码转换为目标代码的复杂系统,通过理解其工作原理,我们可以更好地理解JavaScript的执行过程。

编译器基础概念 🌟

💡 小知识:编译器通常包括词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成等阶段。每个阶段都有其特定的任务和挑战。

词法分析器实现 📊

// 1. Token类型定义
const TokenType = {// 关键字FUNCTION: 'FUNCTION',RETURN: 'RETURN',IF: 'IF',ELSE: 'ELSE',// 标识符和字面量IDENTIFIER: 'IDENTIFIER',NUMBER: 'NUMBER',STRING: 'STRING',// 运算符PLUS: 'PLUS',MINUS: 'MINUS',MULTIPLY: 'MULTIPLY',DIVIDE: 'DIVIDE',// 分隔符LEFT_PAREN: 'LEFT_PAREN',RIGHT_PAREN: 'RIGHT_PAREN',LEFT_BRACE: 'LEFT_BRACE',RIGHT_BRACE: 'RIGHT_BRACE',SEMICOLON: 'SEMICOLON',// 其他EOF: 'EOF'
};// 2. Token类
class Token {constructor(type, value, line, column) {this.type = type;this.value = value;this.line = line;this.column = column;}
}// 3. 词法分析器
class Lexer {constructor(source) {this.source = source;this.tokens = [];this.start = 0;this.current = 0;this.line = 1;this.column = 1;}scanTokens() {while (!this.isAtEnd()) {this.start = this.current;this.scanToken();}this.tokens.push(new Token(TokenType.EOF, null,this.line, this.column));return this.tokens;}scanToken() {const c = this.advance();switch (c) {// 单字符tokencase '(': this.addToken(TokenType.LEFT_PAREN); break;case ')': this.addToken(TokenType.RIGHT_PAREN); break;case '{': this.addToken(TokenType.LEFT_BRACE); break;case '}': this.addToken(TokenType.RIGHT_BRACE); break;case ';': this.addToken(TokenType.SEMICOLON); break;// 运算符case '+': this.addToken(TokenType.PLUS); break;case '-': this.addToken(TokenType.MINUS); break;case '*': this.addToken(TokenType.MULTIPLY); break;case '/':if (this.match('/')) {// 单行注释while (this.peek() !== '\n' && !this.isAtEnd()) {this.advance();}} else {this.addToken(TokenType.DIVIDE);}break;// 忽略空白字符case ' ':case '\r':case '\t':break;case '\n':this.line++;this.column = 1;break;// 字符串case '"': this.string(); break;default:if (this.isDigit(c)) {this.number();} else if (this.isAlpha(c)) {this.identifier();} else {throw new Error(`Unexpected character: ${c} at line ${this.line}`);}break;}}// 辅助方法advance() {this.column++;return this.source.charAt(this.current++);}match(expected) {if (this.isAtEnd()) return false;if (this.source.charAt(this.current) !== expected) return false;this.current++;return true;}peek() {if (this.isAtEnd()) return '\0';return this.source.charAt(this.current);}isAtEnd() {return this.current >= this.source.length;}addToken(type, literal = null) {const text = this.source.substring(this.start, this.current);this.tokens.push(new Token(type, literal || text, this.line, this.column));}
}

语法分析器实现 🚀

// 1. AST节点类型
class ASTNode {constructor(type) {this.type = type;}
}// 2. 表达式节点
class BinaryExpr extends ASTNode {constructor(left, operator, right) {super('BinaryExpr');this.left = left;this.operator = operator;this.right = right;}
}class UnaryExpr extends ASTNode {constructor(operator, right) {super('UnaryExpr');this.operator = operator;this.right = right;}
}class LiteralExpr extends ASTNode {constructor(value) {super('LiteralExpr');this.value = value;}
}// 3. 语法分析器
class Parser {constructor(tokens) {this.tokens = tokens;this.current = 0;}parse() {try {return this.expression();} catch (error) {console.error('Parse error:', error);return null;}}expression() {return this.term();}term() {let expr = this.factor();while (this.match(TokenType.PLUS, TokenType.MINUS)) {const operator = this.previous();const right = this.factor();expr = new BinaryExpr(expr, operator, right);}return expr;}factor() {let expr = this.unary();while (this.match(TokenType.MULTIPLY, TokenType.DIVIDE)) {const operator = this.previous();const right = this.unary();expr = new BinaryExpr(expr, operator, right);}return expr;}unary() {if (this.match(TokenType.MINUS)) {const operator = this.previous();const right = this.unary();return new UnaryExpr(operator, right);}return this.primary();}primary() {if (this.match(TokenType.NUMBER)) {return new LiteralExpr(parseFloat(this.previous().value));}if (this.match(TokenType.LEFT_PAREN)) {const expr = this.expression();this.consume(TokenType.RIGHT_PAREN,"Expect ')' after expression.");return expr;}throw new Error('Expect expression.');}// 辅助方法match(...types) {for (const type of types) {if (this.check(type)) {this.advance();return true;}}return false;}check(type) {if (this.isAtEnd()) return false;return this.peek().type === type;}advance() {if (!this.isAtEnd()) this.current++;return this.previous();}isAtEnd() {return this.peek().type === TokenType.EOF;}peek() {return this.tokens[this.current];}previous() {return this.tokens[this.current - 1];}
}

代码生成器实现 💻

// 1. 代码生成器
class CodeGenerator {constructor() {this.output = '';this.indent = 0;}generate(ast) {return this.visitNode(ast);}visitNode(node) {switch (node.type) {case 'BinaryExpr':return this.generateBinaryExpr(node);case 'UnaryExpr':return this.generateUnaryExpr(node);case 'LiteralExpr':return this.generateLiteralExpr(node);default:throw new Error(`Unknown node type: ${node.type}`);}}generateBinaryExpr(node) {const left = this.visitNode(node.left);const right = this.visitNode(node.right);return `(${left} ${node.operator.value} ${right})`;}generateUnaryExpr(node) {const right = this.visitNode(node.right);return `(${node.operator.value}${right})`;}generateLiteralExpr(node) {return node.value.toString();}
}// 2. 优化器
class Optimizer {optimize(ast) {return this.visitNode(ast);}visitNode(node) {switch (node.type) {case 'BinaryExpr':return this.optimizeBinaryExpr(node);case 'UnaryExpr':return this.optimizeUnaryExpr(node);case 'LiteralExpr':return node;default:throw new Error(`Unknown node type: ${node.type}`);}}optimizeBinaryExpr(node) {const left = this.visitNode(node.left);const right = this.visitNode(node.right);// 常量折叠if (left.type === 'LiteralExpr' && right.type === 'LiteralExpr') {const result = this.evaluateConstExpr(left.value,node.operator.value,right.value);return new LiteralExpr(result);}return new BinaryExpr(left, node.operator, right);}evaluateConstExpr(left, operator, right) {switch (operator) {case '+': return left + right;case '-': return left - right;case '*': return left * right;case '/': return left / right;default:throw new Error(`Unknown operator: ${operator}`);}}
}// 3. 源码映射生成器
class SourceMapGenerator {constructor() {this.mappings = [];this.sources = [];this.names = [];}addMapping(generated, original, source, name) {this.mappings.push({generated,original,source,name});}generate() {return {version: 3,file: 'output.js',sourceRoot: '',sources: this.sources,names: this.names,mappings: this.encodeMappings()};}encodeMappings() {// 实现VLQ编码return this.mappings.map(mapping => {return [mapping.generated.line,mapping.generated.column,mapping.original.line,mapping.original.column].join(',');}).join(';');}
}

实际应用场景 💼

// 1. 简单计算器编译器
class CalculatorCompiler {constructor() {this.lexer = null;this.parser = null;this.generator = null;}compile(source) {// 词法分析this.lexer = new Lexer(source);const tokens = this.lexer.scanTokens();// 语法分析this.parser = new Parser(tokens);const ast = this.parser.parse();// 优化const optimizer = new Optimizer();const optimizedAst = optimizer.optimize(ast);// 代码生成this.generator = new CodeGenerator();return this.generator.generate(optimizedAst);}
}// 2. DSL编译器
class DSLCompiler {constructor(grammar) {this.grammar = grammar;this.lexer = null;this.parser = null;}compile(source) {// 根据语法规则生成词法分析器this.lexer = this.createLexer(source);const tokens = this.lexer.scanTokens();// 根据语法规则生成语法分析器this.parser = this.createParser(tokens);const ast = this.parser.parse();// 生成目标代码return this.generateCode(ast);}createLexer(source) {// 根据语法规则创建自定义词法分析器return new CustomLexer(source, this.grammar.tokens);}createParser(tokens) {// 根据语法规则创建自定义语法分析器return new CustomParser(tokens, this.grammar.rules);}generateCode(ast) {// 根据AST生成目标代码const generator = new CustomCodeGenerator(this.grammar.target);return generator.generate(ast);}
}// 3. 模板编译器
class TemplateCompiler {constructor() {this.cache = new Map();}compile(template) {if (this.cache.has(template)) {return this.cache.get(template);}const tokens = this.tokenize(template);const ast = this.parse(tokens);const code = this.generate(ast);const render = new Function('data', code);this.cache.set(template, render);return render;}tokenize(template) {const tokens = [];let current = 0;while (current < template.length) {if (template[current] === '{' && template[current + 1] === '{') {// 处理表达式current += 2;let expr = '';while (current < template.length && !(template[current] === '}' && template[current + 1] === '}')) {expr += template[current];current++;}tokens.push({type: 'expression',value: expr.trim()});current += 2;} else {// 处理文本let text = '';while (current < template.length && !(template[current] === '{' && template[current + 1] === '{')) {text += template[current];current++;}tokens.push({type: 'text',value: text});}}return tokens;}
}

性能优化技巧 ⚡

// 1. 缓存优化
class CompilerCache {constructor() {this.tokenCache = new Map();this.astCache = new Map();this.codeCache = new Map();}getTokens(source) {const hash = this.hashSource(source);if (this.tokenCache.has(hash)) {return this.tokenCache.get(hash);}const tokens = new Lexer(source).scanTokens();this.tokenCache.set(hash, tokens);return tokens;}getAST(tokens) {const hash = this.hashTokens(tokens);if (this.astCache.has(hash)) {return this.astCache.get(hash);}const ast = new Parser(tokens).parse();this.astCache.set(hash, ast);return ast;}getCode(ast) {const hash = this.hashAST(ast);if (this.codeCache.has(hash)) {return this.codeCache.get(hash);}const code = new CodeGenerator().generate(ast);this.codeCache.set(hash, code);return code;}hashSource(source) {// 实现源码哈希return source.length + source.slice(0, 100);}hashTokens(tokens) {// 实现tokens哈希return tokens.map(t => t.type + t.value).join('');}hashAST(ast) {// 实现AST哈希return JSON.stringify(ast);}
}// 2. 并行处理
class ParallelCompiler {constructor(workerCount = navigator.hardwareConcurrency) {this.workers = [];this.initWorkers(workerCount);}async initWorkers(count) {for (let i = 0; i < count; i++) {const worker = new Worker('compiler-worker.js');this.workers.push(worker);}}async compile(sources) {const chunks = this.splitSources(sources);const promises = chunks.map((chunk, index) => {return new Promise((resolve, reject) => {const worker = this.workers[index % this.workers.length];worker.onmessage = e => resolve(e.data);worker.onerror = reject;worker.postMessage({ type: 'compile', sources: chunk });});});const results = await Promise.all(promises);return this.mergeResults(results);}splitSources(sources) {// 将源码分割成多个块const chunkSize = Math.ceil(sources.length / this.workers.length);const chunks = [];for (let i = 0; i < sources.length; i += chunkSize) {chunks.push(sources.slice(i, i + chunkSize));}return chunks;}
}// 3. 增量编译
class IncrementalCompiler {constructor() {this.cache = new CompilerCache();this.dependencies = new Map();this.modifiedFiles = new Set();}markFileModified(file) {this.modifiedFiles.add(file);// 标记依赖文件const deps = this.dependencies.get(file) || new Set();for (const dep of deps) {this.markFileModified(dep);}}async compile(files) {const results = new Map();for (const file of files) {if (!this.modifiedFiles.has(file) && this.cache.has(file)) {results.set(file, this.cache.get(file));continue;}const result = await this.compileFile(file);results.set(file, result);this.cache.set(file, result);this.modifiedFiles.delete(file);}return results;}async compileFile(file) {const source = await this.readFile(file);const tokens = this.cache.getTokens(source);const ast = this.cache.getAST(tokens);// 收集依赖this.collectDependencies(file, ast);return this.cache.getCode(ast);}collectDependencies(file, ast) {const deps = new Set();this.traverseAST(ast, node => {if (node.type === 'Import') {deps.add(node.source);}});this.dependencies.set(file, deps);}
}

最佳实践建议 💡

  1. 错误处理和恢复
// 1. 错误收集器
class ErrorCollector {constructor() {this.errors = [];}addError(error) {this.errors.push({message: error.message,line: error.line,column: error.column,phase: error.phase});}hasErrors() {return this.errors.length > 0;}getErrors() {return this.errors;}clear() {this.errors = [];}
}// 2. 错误恢复策略
class ErrorRecovery {static recoverFromSyntaxError(parser) {// 跳过到下一个同步点while (!parser.isAtEnd()) {if (parser.match(TokenType.SEMICOLON)) return;if (parser.peek().type === TokenType.RIGHT_BRACE) return;parser.advance();}}
}// 3. 诊断信息生成
class DiagnosticReporter {constructor(source) {this.source = source;this.lines = source.split('\n');}report(error) {const line = this.lines[error.line - 1];const pointer = ' '.repeat(error.column - 1) + '^';return [`Error: ${error.message}`,`  at line ${error.line}, column ${error.column}`,line,pointer,`Phase: ${error.phase}`].join('\n');}
}

结语 📝

JavaScript编译器的实现是一个复杂但有趣的主题。通过本文,我们学习了:

  1. 编译器的基本架构和工作原理
  2. 词法分析和语法分析的实现
  3. 代码生成和优化技术
  4. 性能优化策略
  5. 错误处理和最佳实践

💡 学习建议:在实现编译器时,要注意模块化设计和错误处理。合理使用缓存和优化策略,可以显著提升编译性能。同时,良好的错误提示对于开发者体验至关重要。


如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇

终身学习,共同成长。

咱们下一期见

💻

相关文章:

JavaScript系列(50)--编译器实现详解

JavaScript编译器实现详解 &#x1f528; 今天&#xff0c;让我们深入探讨JavaScript编译器的实现。编译器是一个将源代码转换为目标代码的复杂系统&#xff0c;通过理解其工作原理&#xff0c;我们可以更好地理解JavaScript的执行过程。 编译器基础概念 &#x1f31f; &…...

大数据相关职位 职业进阶路径

大数据相关职位 & 职业进阶路径 &#x1f4cc; 大数据相关职位 & 职业进阶路径 大数据领域涵盖多个方向&#xff0c;包括数据工程、数据分析、数据治理、数据科学等&#xff0c;每个方向的进阶路径有所不同。以下是大数据相关职位的详细解析及其职业进阶关系。 &#…...

基础项目实战——学生管理系统(c++)

目录 前言一、功能菜单界面二、类与结构体的实现三、录入学生信息四、删除学生信息五、更改学生信息六、查找学生信息七、统计学生人数八、保存学生信息九、读取学生信息十、打印所有学生信息十一、退出系统十二、文件拆分结语 前言 这一期我们来一起学习我们在大学做过的课程…...

C++,STL,【目录篇】

文章目录 一、简介二、内容提纲第一部分&#xff1a;STL 概述第二部分&#xff1a;STL 容器第三部分&#xff1a;STL 迭代器第四部分&#xff1a;STL 算法第五部分&#xff1a;STL 函数对象第六部分&#xff1a;STL 高级主题第七部分&#xff1a;STL 实战应用 三、写作风格四、…...

【Rust自学】15.3. Deref trait Pt.2:隐式解引用转化与可变性

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 15.3.1. 函数和方法的隐式解引用转化(Deref Coercion) 隐式解引用转化(Deref Coercion)是为函数和方法提供的一种便捷特性。 它的原理是…...

密码强度验证代码解析:C语言实现与细节剖析

在日常的应用开发中&#xff0c;密码强度验证是保障用户账户安全的重要环节。今天&#xff0c;我们就来深入分析一段用C语言编写的密码强度验证代码&#xff0c;看看它是如何实现对密码强度的多维度检测的。 代码整体结构 这段C语言代码主要实现了对输入密码的一系列规则验证&a…...

arkts bridge使用示例

接上一篇&#xff1a;arkui-x跨平台与android java联合开发-CSDN博客 本篇讲前端arkui如何与后端其他平台进行数据交互&#xff0c;接上一篇&#xff0c;后端os平台为Android java。 arkui-x框架提供了一个独特的机制&#xff1a;bridge。 1、前端接口定义实现 定义一个bri…...

LINUX部署微服务项目步骤

项目简介技术栈 主体技术&#xff1a;SpringCloud&#xff0c;SpringBoot&#xff0c;VUE2&#xff0c; 中间件&#xff1a;RabbitMQ、Redis 创建用户 在linux服务器home下创建用户qshh&#xff0c;用于后续本项目需要的环境进行安装配置 #创建用户 useradd 用户名 #设置登录密…...

zsh安装插件

0 zsh不仅在外观上比较美观&#xff0c;而且其具有强大的插件&#xff0c;如果不使用那就亏大了。 官方插件库 https://github.com/ohmyzsh/ohmyzsh/wiki/Plugins 官方插件库并不一定有所有的插件&#xff0c;比如zsh-autosuggestions插件就不再列表里&#xff0c;下面演示zs…...

网站如何正式上线(运维详解)

因为平台原因&#xff0c;不能有太多链接&#xff0c;所以下文中链接都删除了&#xff0c;想访问的去原文链接&#xff1a;https://www.zhoudongqi.com/ TIPS 这篇文章是我自己运营运维的wordpess站点的经验总结&#xff0c;可以说十分详细&#xff0c;域名&#xff0c;服务器和…...

SQL server 数据库使用整理

标题&#xff1a;SQL server 数据库使用整理 1.字符串表名多次查询 2.读取SQL中Json字段中的值&#xff1a;JSON_VALUE&#xff08;最新版本支持&#xff0c;属性名大小写敏感&#xff09; 1.字符串表名多次查询 SELECT ROW_NUMBER() OVER (ORDER BY value ASC) rowid,value…...

【Rust自学】17.2. 使用trait对象来存储不同值的类型

喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文&#xff09;&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 17.2.1. 需求 这篇文章以一个例子来介绍如何在Rust中使用trait对象来存储不同值的类型。 …...

初始化mysql报错cannot open shared object file: No such file or directory

报错展示 我在初始化msyql的时候报错&#xff1a;mysqld: error while loading shared libraries: libaio.so.1: cannot open shared object file: No such file or directory 解读&#xff1a; libaio包的作用是为了支持同步I/O。对于数据库之类的系统特别重要&#xff0c;因此…...

2025年1月22日(网络编程)

系统信息&#xff1a; ubuntu 16.04LTS Raspberry Pi Zero 2W 系统版本&#xff1a; 2024-10-22-raspios-bullseye-armhf Python 版本&#xff1a;Python 3.9.2 已安装 pip3 支持拍摄 1080p 30 (1092*1080), 720p 60 (1280*720), 60/90 (640*480) 已安装 vim 已安装 git 学习…...

Jason配置环境变量

jason官网 https://jason-lang.github.io/ https://github.com/jason-lang/jason/releases 步骤 安装 Java 21 或更高版本 安装 Visual Studio Code 根据操作系统&#xff0c;请按照以下具体步骤操作 视窗 下载 Jason 的最新版本&#xff0c;选择“jason-bin-3.3.0.zip”…...

蓝桥杯python语言基础(7)——自定义排序和二分查找

目录 一、自定义排序 &#xff08;一&#xff09;sorted &#xff08;二&#xff09;list.sort 二、二分查找 bisect 一、自定义排序 &#xff08;一&#xff09;sorted sorted() 函数会返回一个新的已排序列表&#xff0c;而列表的 sort() 方法会直接在原列表上进行排序…...

(开源)基于Django+Yolov8+Tensorflow的智能鸟类识别平台

1 项目简介&#xff08;开源地址在文章结尾&#xff09; 系统旨在为了帮助鸟类爱好者、学者、动物保护协会等群体更好的了解和保护鸟类动物。用户群体可以通过平台采集野外鸟类的保护动物照片和视频&#xff0c;甄别分类、实况分析鸟类保护动物&#xff0c;与全世界各地的用户&…...

后盾人JS--闭包明明白白

延伸函数环境生命周期 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> <…...

redis的分片集群模式

redis的分片集群模式 1 主从哨兵集群的问题和分片集群特点 主从哨兵集群可应对高并发写和高可用性&#xff0c;但是还有2个问题没有解决&#xff1a; &#xff08;1&#xff09;海量数据存储 &#xff08;2&#xff09;高并发写的问题 使用分片集群可解决&#xff0c;分片集群…...

Kiwi 安卓浏览器本月停止维护,扩展功能迁移至 Edge Canary

IT之家 1 月 25 日消息&#xff0c;科技媒体 Android Authority 今天&#xff08;1 月 25 日&#xff09;发布博文&#xff0c;报道称 Kiwi 安卓浏览器将于本月停止维护&#xff0c;相关扩展支持功能已整合到微软 Edge Canary 浏览器中。 开发者 Arnaud42 表示 Kiwi 安卓浏览器…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用

文章目录 一、背景知识&#xff1a;什么是 B-Tree 和 BTree&#xff1f; B-Tree&#xff08;平衡多路查找树&#xff09; BTree&#xff08;B-Tree 的变种&#xff09; 二、结构对比&#xff1a;一张图看懂 三、为什么 MySQL InnoDB 选择 BTree&#xff1f; 1. 范围查询更快 2…...