适合有Java/Python基础的前端工程师,30分钟快速了解核心概念,应对面试提问


📘 Part 1: C++ 快速入门

🎯 核心定位

C++是什么?

  • 高性能的编译型语言,C语言的扩展
  • 支持面向对象、泛型编程、底层操作
  • 用于系统开发、游戏引擎、性能敏感场

与Java/Python对比:

Java/Python: 自动内存管理,跨平台虚拟机,开发效率高
C++: 手动内存管理,直接编译为机器码,性能最高,但容易出错

1️⃣ 基础语法 (与Java对比)

程序入口
// C++ 版本
#include <iostream>
using namespace std;

int main() {
    cout << "Hello World" << endl;
    return 0;
}

// Java 版本
public class Main {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

关键区别:

  • C++没有类包裹,main函数直接写
  • #include相当于import,<iostream>是输入输出库
  • cout相当于System.out,<<是输出运算符
  • endl相当于\n换行
变量声明
// C++: 类型在前,名字在后
int age = 25;
string name = "张三";  // 需要 #include <string>
double price = 99.9;
bool isActive = true;

// 自动推断类型 (C++11)
auto count = 10;  // 自动推断为int
auto message = "Hello";  // 推断为const char*

// Java对比
int age = 25;
String name = "张三";
double price = 99.9;
boolean isActive = true;
var count = 10;  // Java 10+

2️⃣ 指针和引用 

指针 (Pointer)
int num = 10;
int* ptr = &num;  // ptr存储num的内存地址

cout << num;      // 输出: 10 (值)
cout << &num;     // 输出: 0x7fff... (地址)
cout << ptr;      // 输出: 0x7fff... (地址)
cout << *ptr;     // 输出: 10 (解引用,获取地址指向的值)

*ptr = 20;        // 通过指针修改值
cout << num;      // 输出: 20 (原变量被改变)

关键概念:

  • & = 取地址运算符 (获取变量的内存地址)
  • * = 解引用运算符 (访问指针指向的值)
  • int* = 指针类型 (指向int的指针)

类比理解:

变量 = 房子
地址 = 门牌号
指针 = 记录门牌号的便签

&num  → 查看房子的门牌号
ptr   → 便签上写的门牌号
*ptr  → 根据便签找到房子,看里面的内容
引用 (Reference)
int num = 10;
int& ref = num;   // ref是num的别名

ref = 20;         // 修改ref就是修改num
cout << num;      // 输出: 20

// Java没有真正的引用,但对象传递类似

指针 vs 引用:

指针:
- 可以为空 (nullptr)
- 可以改变指向
- 需要解引用 (*)

引用:
- 不能为空
- 不能改变引用对象
- 直接使用,不需要解引用

3️⃣ 内存管理

栈 vs 堆
// 栈内存: 自动管理,作用域结束自动释放
void func() {
    int x = 10;  // 栈上分配
}  // x自动销毁

// 堆内存: 手动管理,需要手动释放
void func() {
    int* ptr = new int(10);  // 堆上分配
    // ... 使用ptr
    delete ptr;              // 必须手动释放!
    ptr = nullptr;           // 防止野指针
}

// 数组的堆分配
int* arr = new int[100];
delete[] arr;  // 注意要用delete[]

内存泄漏示例:

void badFunction() {
    int* data = new int(100);
    // 忘记delete!
}  // data指针被销毁,但堆内存没释放 → 内存泄漏!

类比Java:

// Java: 垃圾回收器自动管理
void func() {
    Integer x = new Integer(10);
    // 不用管释放,GC会处理
}
智能指针
#include <memory>

// unique_ptr: 独占所有权
unique_ptr<int> ptr1(new int(10));
// unique_ptr<int> ptr2 = ptr1;  // 错误!不能复制

// shared_ptr: 共享所有权,引用计数
shared_ptr<int> ptr1 = make_shared<int>(10);
shared_ptr<int> ptr2 = ptr1;  // OK,引用计数+1
// 两个都销毁后,内存才释放

// weak_ptr: 弱引用,不增加引用计数

4️⃣ 类和对象

// 定义类
class Student {
private:
    string name;
    int age;

public:
    // 构造函数
    Student(string n, int a) : name(n), age(a) {}
    
    // 成员函数
    void display() {
        cout << "Name: " << name << ", Age: " << age << endl;
    }
    
    // getter/setter
    string getName() { return name; }
    void setName(string n) { name = n; }
};

// 使用
Student s1("张三", 20);  // 栈上创建
s1.display();

Student* s2 = new Student("李四", 22);  // 堆上创建
s2->display();  // 指针用->访问成员
delete s2;

与Java对比:

C++:
- 可以栈上创建对象 (自动管理)
- 可以堆上创建对象 (需手动管理)
- 指针访问成员用 ->
- 对象访问成员用 .

Java:
- 所有对象都在堆上
- 都是引用访问
- 统一用 . 访问成员

5️⃣ 面试常问概念

Q: 什么是指针?为什么需要指针?
A: 指针是存储内存地址的变量。需要指针因为:
   1. 动态内存分配
   2. 高效传递大对象(传地址比复制快)
   3. 数据结构(链表、树等)
   4. 与底层系统交互
Q: 什么是内存泄漏?
A: 程序申请了堆内存但忘记释放,导致内存无法回收。
   例如: new了对象但没有delete,随着程序运行内存占用越来越高。
Q: C++和C的区别?
A: C++是C的超集,主要增加了:
   1. 面向对象(类、继承、多态)
   2. 模板(泛型编程)
   3. 异常处理
   4. 命名空间
   5. STL标准库
Q: C++的优缺点?
优点:
- 性能极高,接近硬件
- 灵活,底层控制力强
- 适合系统开发、游戏引擎

缺点:
- 学习曲线陡峭
- 容易出内存错误
- 开发效率相对低
- 跨平台需要重新编译

🟢 Part 2: Node.js 快速入门

🎯 核心定位

Node.js是什么?

  • JavaScript的后端运行环境
  • 基于Chrome V8引擎
  • 事件驱动、非阻塞I/O
  • 适合I/O密集型应用(API服务、实时应用)

与Python对比:

Node.js: 异步非阻塞,单线程事件循环,适合高并发I/O
Python: 同步阻塞为主,多线程/多进程,适合数据处理/AI

1️⃣ 基础概念

运行JS文件
# 创建文件 app.js
node app.js

# 交互式环境(REPL)
node
> console.log("Hello")
模块系统 (CommonJS)
// math.js - 导出模块
function add(a, b) {
    return a + b;
}

function subtract(a, b) {
    return a - b;
}

module.exports = { add, subtract };
// 或: exports.add = add;

// app.js - 导入模块
const math = require('./math');
console.log(math.add(5, 3));  // 8

// 导入内置模块
const fs = require('fs');
const http = require('http');

与前端ES6模块对比:

// CommonJS (Node.js)
const module = require('./module');
module.exports = { ... };

// ES6 (前端)
import module from './module';
export default { ... };

// 注意: Node.js也支持ES6模块,需要配置

2️⃣ 异步编程

回调函数 (Callback)
const fs = require('fs');

// 异步读取文件
fs.readFile('data.txt', 'utf8', (err, data) => {
    if (err) {
        console.error('读取失败:', err);
        return;
    }
    console.log('文件内容:', data);
});

console.log('这行会先执行!');

执行顺序:

1. 发起读取文件请求
2. 立即执行下一行 (不等待文件读取完成)
3. 输出"这行会先执行!"
4. 文件读取完成后,调用回调函数
5. 输出文件内容
回调地狱 (Callback Hell)
// 糟糕的写法: 嵌套太深
fs.readFile('file1.txt', (err, data1) => {
    if (err) return console.error(err);
    fs.readFile('file2.txt', (err, data2) => {
        if (err) return console.error(err);
        fs.readFile('file3.txt', (err, data3) => {
            if (err) return console.error(err);
            console.log(data1, data2, data3);
        });
    });
});
Promise (解决方案1)
const fs = require('fs').promises;

// 链式调用
fs.readFile('file1.txt', 'utf8')
    .then(data1 => {
        console.log(data1);
        return fs.readFile('file2.txt', 'utf8');
    })
    .then(data2 => {
        console.log(data2);
    })
    .catch(err => {
        console.error('出错了:', err);
    });
async/await (解决方案2)
const fs = require('fs').promises;

async function readFiles() {
    try {
        const data1 = await fs.readFile('file1.txt', 'utf8');
        const data2 = await fs.readFile('file2.txt', 'utf8');
        console.log(data1, data2);
    } catch (err) {
        console.error('出错了:', err);
    }
}

readFiles();

3️⃣ 常用内置模块

fs (文件系统)
const fs = require('fs');

// 同步读取 (阻塞)
const data = fs.readFileSync('file.txt', 'utf8');

// 异步读取 (非阻塞,推荐)
fs.readFile('file.txt', 'utf8', (err, data) => {
    if (err) throw err;
    console.log(data);
});

// 写入文件
fs.writeFile('output.txt', 'Hello', err => {
    if (err) throw err;
    console.log('写入成功');
});

// 检查文件是否存在
if (fs.existsSync('file.txt')) {
    console.log('文件存在');
}
http (创建服务器)
const http = require('http');

const server = http.createServer((req, res) => {
    // req: 请求对象
    // res: 响应对象
    
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Hello World\n');
});

server.listen(3000, () => {
    console.log('服务器运行在 http://localhost:3000');
});
path (路径处理)
const path = require('path');

const filePath = '/users/zhang/documents/file.txt';

path.basename(filePath);  // 'file.txt'
path.dirname(filePath);   // '/users/zhang/documents'
path.extname(filePath);   // '.txt'

// 拼接路径 (跨平台)
const fullPath = path.join(__dirname, 'data', 'file.txt');
// Windows: C:\project\data\file.txt
// Linux:   /project/data/file.txt

4️⃣ Express框架 (快速搭建API)

安装和基础使用
npm install express
const express = require('express');
const app = express();

// 中间件: 解析JSON请求体
app.use(express.json());

// GET请求
app.get('/', (req, res) => {
    res.send('Hello World');
});

// GET请求带参数
app.get('/user/:id', (req, res) => {
    const userId = req.params.id;
    res.json({ id: userId, name: '张三' });
});

// POST请求
app.post('/api/login', (req, res) => {
    const { username, password } = req.body;
    // 验证逻辑...
    res.json({ success: true, token: 'xxx' });
});

// 启动服务器
app.listen(3000, () => {
    console.log('服务器运行在 3000 端口');
});
实际项目结构
project/
├── app.js           # 入口文件
├── routes/          # 路由
│   ├── user.js
│   └── product.js
├── controllers/     # 控制器(业务逻辑)
│   └── userController.js
├── models/          # 数据模型
│   └── User.js
├── middleware/      # 中间件
│   └── auth.js
└── package.json

5️⃣ NPM包管理

常用命令
# 初始化项目
npm init -y

# 安装依赖
npm install express
npm i express  # 简写

# 安装开发依赖
npm install --save-dev nodemon

# 全局安装
npm install -g pm2

# 安装指定版本
npm install express@4.17.1

# 卸载
npm uninstall express

# 查看已安装的包
npm list
package.json
{
  "name": "my-app",
  "version": "1.0.0",
  "description": "我的Node.js应用",
  "main": "app.js",
  "scripts": {
    "start": "node app.js",
    "dev": "nodemon app.js",
    "test": "jest"
  },
  "dependencies": {
    "express": "^4.18.0"
  },
  "devDependencies": {
    "nodemon": "^2.0.20"
  }
}

版本号说明:

^4.18.0  → 允许小版本更新 (4.x.x)
~4.18.0  → 允许补丁版本更新 (4.18.x)
4.18.0   → 锁定版本
*        → 最新版本

6️⃣ 事件循环 (Event Loop)

核心概念
Node.js是单线程的,但通过事件循环实现异步非阻塞

执行顺序:
1. 同步代码
2. 微任务 (Promise.then, process.nextTick)
3. 宏任务 (setTimeout, setInterval, I/O)
示例
console.log('1: 同步代码');

setTimeout(() => {
    console.log('2: setTimeout (宏任务)');
}, 0);

Promise.resolve().then(() => {
    console.log('3: Promise (微任务)');
});

console.log('4: 同步代码');

// 输出顺序: 1 → 4 → 3 → 2

为什么这样?

1. 执行同步代码: 输出 1, 4
2. 检查微任务队列: 执行Promise,输出 3
3. 检查宏任务队列: 执行setTimeout,输出 2

7️⃣ 实战案例: RESTful API

const express = require('express');
const app = express();

app.use(express.json());

// 模拟数据库
let users = [
    { id: 1, name: '张三', age: 20 },
    { id: 2, name: '李四', age: 22 }
];

// 获取所有用户
app.get('/api/users', (req, res) => {
    res.json(users);
});

// 获取单个用户
app.get('/api/users/:id', (req, res) => {
    const user = users.find(u => u.id === parseInt(req.params.id));
    if (!user) return res.status(404).json({ error: '用户不存在' });
    res.json(user);
});

// 创建用户
app.post('/api/users', (req, res) => {
    const newUser = {
        id: users.length + 1,
        name: req.body.name,
        age: req.body.age
    };
    users.push(newUser);
    res.status(201).json(newUser);
});

// 更新用户
app.put('/api/users/:id', (req, res) => {
    const user = users.find(u => u.id === parseInt(req.params.id));
    if (!user) return res.status(404).json({ error: '用户不存在' });
    
    user.name = req.body.name;
    user.age = req.body.age;
    res.json(user);
});

// 删除用户
app.delete('/api/users/:id', (req, res) => {
    const index = users.findIndex(u => u.id === parseInt(req.params.id));
    if (index === -1) return res.status(404).json({ error: '用户不存在' });
    
    users.splice(index, 1);
    res.status(204).send();
});

app.listen(3000, () => {
    console.log('API服务器运行在 3000 端口');
});

8️⃣ 常见问题

Q: Node.js的优缺点?
优点:
- 前后端统一用JavaScript
- 异步非阻塞,适合高并发I/O
- npm生态丰富
- 开发效率高

缺点:
- 单线程,CPU密集型任务性能差
- 回调地狱(已被async/await解决)
- 错误处理不当会导致进程崩溃
Q: Node.js是单线程还是多线程?
A: 主线程是单线程,但底层有线程池处理I/O操作。
   
   用户代码在单线程运行,通过事件循环处理异步任务。
   I/O操作(文件读写、网络请求)由libuv线程池处理。
   
   适合: I/O密集型任务
   不适合: CPU密集型任务(如复杂计算、图像处理)
Q: 什么是中间件(Middleware)?
A: 在Express中,中间件是处理请求的函数,按顺序执行。

   例如:
   - 日志记录中间件: 记录每个请求
   - 身份验证中间件: 检查用户是否登录
   - 错误处理中间件: 统一处理错误

   app.use((req, res, next) => {
       console.log('请求:', req.url);
       next();  // 传递给下一个中间件
   });
Q: Promise和async/await的区别?
A: async/await是Promise的语法糖,让异步代码看起来像同步代码。

   Promise: .then()链式调用
   async/await: 用try/catch处理错误,代码更简洁

   本质上async函数返回的也是Promise。

📊 总结对比

特性 C++ Node.js
类型 编译型语言 运行时环境(JavaScript)
性能 极高 中等(V8优化后较快)
内存管理 手动(new/delete) 自动(垃圾回收)
并发模型 多线程 单线程+事件循环
适用场景 系统开发、游戏引擎 API服务、实时应用
学习曲线 陡峭 平缓(对前端友好)
与岗位关系 Electron原生模块 桌面应用后端逻辑
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐