C++ 基础与核心概念

Node.js 的高性能源于其底层实现,这些模块主要由 C++ 编写。因此,理解 Node.js 底层组成及掌握 C++ 核心概念是深入学习的关键。

1. Node.js 底层组成

Node.js 是基于 Chrome V8 引擎的 JavaScript 运行时,其高效的事件驱动和非阻塞 I/O 能力由以下核心组件实现:

1.1 V8 引擎

  • 功能:解析和执行 JS 代码,通过 JIT 编译转为机器码。
  • 实现 :C++ 编写,管理 JS 对象、内存分配(垃圾回收)和执行上下文(如 IsolateContext)。
  • 作用:执行 JS 代码,如事件回调、Promise。

1.2 libuv 库

  • 功能:跨平台异步 I/O,负责事件循环、线程池和非阻塞 I/O(文件、网络)。
  • 实现:主要 C,部分 C++,提供事件循环、句柄和流。
  • 作用 :实现事件驱动,处理异步任务(如 setTimeout、文件操作)。

1.3 C++ 绑定层

  • 功能 :桥接 V8 和 libuv,核心模块(如 fshttp)通过 C++ 实现。
  • 实现:使用 C++ 和 N-API。
  • 作用:提供 JS 与底层的接口,如 Buffer 内存管理。

1.4 其他组件

  • c-ares:异步 DNS 解析。
  • OpenSSL:HTTPS 和加密。
  • zlib:压缩(如 gzip)。
  • http-parser:HTTP 请求/响应解析。

2. C++ 基础与核心概念

Node.js 底层依赖 C++,以下结合 Node.js 场景讲解 C++ 基础和核心概念。

2.1 C++ 基础语法

C++ 是高效的系统级语言,支持过程式、面向对象和泛型编程,注重手动内存管理和性能。

2.1.1 基本结构

c 复制代码
#include <iostream>

int main() {
    std::cout << "Hello, Node.js from C++!" << std::endl;
    return 0;
}
  • 头文件#include 引入库,std:: 是标准命名空间。
  • main 函数:程序入口。
  • 编译g++ hello.cpp -o hello && ./hello.

2.1.2 数据类型

C++ 是强类型语言:

  • 整数:intlong.
  • 浮点:floatdouble.
  • 字符:char.
  • 布尔:bool.
ini 复制代码
int age = 25;
double pi = 3.14159;
char grade = 'A';
bool isNodeDeveloper = true;

const int MAX_AGE = 100;
enum Color { RED, GREEN, BLUE };
Color myColor = RED;

V8 用 double 表示 JS Number。

2.1.3 控制结构

  • 条件:if-elseswitch.
  • 循环:forwhile.
ini 复制代码
#include <iostream>

int main() {
    int n = 10;
    long long fib[10];
    fib[0] = 0;
    fib[1] = 1;
    for (int i = 2; i < n; ++i) {
        fib[i] = fib[i-1] + fib[i-2];
    }
    for (int i = 0; i < n; ++i) {
        std::cout << fib[i] << " ";
    }
    std::cout << std::endl;
    return 0;
}

2.1.4 函数

c 复制代码
int add(int a, int b) {
    return a + b;
}

int main() {
    std::cout << add(5, 3) << std::endl;  // 8
    return 0;
}

Node.js 扩展用 C++ 函数定义导出方法。

2.1.5 类和面向对象编程

C++ 的面向对象编程(OOP)是其核心特性,支持封装、继承、多态和抽象,广泛用于 Node.js 底层(如 V8 的 IsolateContext)。

2.1.5.1 封装

封装通过类将数据和方法绑定,访问控制(publicprivateprotected)保护数据。

c 复制代码
#include <string>
#include <iostream>

class Person {
private:
    std::string name;
    int age;
public:
    Person(std::string n, int a) : name(n), age(a) {}
    void setName(std::string n) { name = n; }
    std::string getName() const { return name; }
    void greet() const { std::cout << "Hello, I'm " << name << ", age " << age << std::endl; }
};

int main() {
    Person p("NodeDev", 30);
    p.greet();  // Hello, I'm NodeDev, age 30
    p.setName("JSDev");
    std::cout << p.getName() << std::endl;  // JSDev
    return 0;
}
  • 应用 :V8 的类(如 v8::Object)用封装管理 JS 对象属性。
2.1.5.2 继承

继承允许子类复用父类代码,支持代码重用和层次结构。

c 复制代码
#include <string>
#include <iostream>

class Person {
protected:
    std::string name;
public:
    Person(std::string n) : name(n) {}
    virtual void greet() const { std::cout << "I'm " << name << std::endl; }
};

class Developer : public Person {
private:
    std::string language;
public:
    Developer(std::string n, std::string lang) : Person(n), language(lang) {}
    void greet() const override {
        std::cout << "I'm " << name << ", a " << language << " developer" << std::endl;
    }
};

int main() {
    Developer dev("NodeDev", "JavaScript");
    dev.greet();  // I'm NodeDev, a JavaScript developer
    return 0;
}
  • virtual 和 override:支持多态,子类可重写父类虚函数。
  • 应用 :V8 的对象层次结构(如 v8::Value 的子类 v8::Objectv8::Function)。
2.1.5.3 多态

多态通过虚函数和指针/引用实现运行时行为动态选择。

arduino 复制代码
#include <iostream>

class Shape {
public:
    virtual double area() const = 0;  // 纯虚函数,抽象类
    virtual ~Shape() = default;  // 虚析构函数
};

class Circle : public Shape {
private:
    double radius;
public:
    Circle(double r) : radius(r) {}
    double area() const override { return 3.14159 * radius * radius; }
};

int main() {
    Shape* shape = new Circle(5.0);
    std::cout << "Area: " << shape->area() << std::endl;  // Area: 78.5397
    delete shape;
    return 0;
}
  • 应用 :V8 的多态类(如 v8::Value)处理不同 JS 类型。
2.1.5.4 抽象和接口

纯虚函数定义接口,强制子类实现。

arduino 复制代码
#include <iostream>

class Printable {
public:
    virtual void print() const = 0;
    virtual ~Printable() = default;
};

class Document : public Printable {
public:
    void print() const override { std::cout << "Printing document" << std::endl; }
};

int main() {
    Printable* doc = new Document();
    doc->print();  // Printing document
    delete doc;
    return 0;
}
  • 应用 :libuv 的句柄(如 uv_handle_t)通过抽象类定义通用接口。
2.1.5.5 OOP 在 Node.js 底层
  • V8IsolateContext 使用类封装运行时状态,继承和多态管理对象层次。
  • libuv:句柄和流通过抽象类实现跨平台接口。
  • N-API:类封装 JS 对象操作,简化扩展开发。

2.2 核心概念一:指针

2.2.1 指针基础

c 复制代码
#include <iostream>

int main() {
    int x = 10;
    int* ptr = &x;
    std::cout << "x: " << x << std::endl;       // 10
    std::cout << "ptr: " << ptr << std::endl;   // 地址
    std::cout << "*ptr: " << *ptr << std::endl; // 10
    return 0;
}

2.2.2 指针运算和数组

c 复制代码
int arr[3] = {1, 2, 3};
int* p = arr;
for (int i = 0; i < 3; ++i) {
    std::cout << *(p + i) << " ";  // 1 2 3
}
std::cout << std::endl;

Node.js 的 Buffer 是 char* 指针数组。

2.2.3 动态内存

ini 复制代码
int* dynamicPtr = new int;
*dynamicPtr = 42;
std::cout << *dynamicPtr << std::endl;  // 42
delete dynamicPtr;
dynamicPtr = nullptr;

2.2.4 智能指针

c 复制代码
#include <memory>
#include <iostream>

struct Node {
    int data;
    Node(int d) : data(d) { std::cout << "Node created\n"; }
    ~Node() { std::cout << "Node destroyed\n"; }
};

int main() {
    std::shared_ptr<Node> ptr1 = std::make_shared<Node>(42);
    std::cout << ptr1->data << std::endl;  // 42
    return 0;
}

V8 的 v8::Persistent 使用类似机制。

2.2.5 指针陷阱

  • 空指针:访问 nullptr 崩溃。
  • 野指针:释放后未置空。
  • 越界:访问数组边界外。

2.3 核心概念二:引用

c 复制代码
#include <iostream>

int main() {
    int x = 10;
    int& ref = x;
    ref = 20;
    std::cout << "x: " << x << std::endl;  // 20
    return 0;
}
  • 应用 :V8 的 v8::Local 传递对象,N-API 用引用管理回调。

2.4 核心概念三:内存管理

2.4.1 栈与堆

c 复制代码
int* createArray(int size) {
    int* arr = new int[size];
    for (int i = 0; i < size; ++i) {
        arr[i] = i;
    }
    return arr;
}

int main() {
    int* arr = createArray(5);
    for (int i = 0; i < 5; ++i) {
        std::cout << arr[i] << " ";  // 0 1 2 3 4
    }
    std::cout << std::endl;
    delete[] arr;
    return 0;
}

2.4.2 RAII

资源获取即初始化,libuv 的句柄基于此。

2.5 核心概念四:模板

2.5.1 模板函数

c 复制代码
#include <iostream>

template <typename T>
T max(T a, T b) {
    return a > b ? a : b;
}

int main() {
    std::cout << max(5, 3) << std::endl;      // 5
    std::cout << max(3.14, 2.71) << std::endl; // 3.14
    return 0;
}

2.5.2 模板类

c 复制代码
#include <iostream>
#include <string>

template <typename T>
class Box {
    T value;
public:
    Box(T v) : value(v) {}
    T getValue() const { return value; }
};

int main() {
    Box<int> intBox(42);
    Box<std::string> strBox("Node.js");
    std::cout << intBox.getValue() << std::endl;  // 42
    std::cout << strBox.getValue() << std::endl;  // Node.js
    return 0;
}
  • 应用 :V8 的 v8::Local<T>,libuv 平台抽象。

2.6 核心概念五:多线程

2.6.1 线程

c 复制代码
#include <iostream>
#include <thread>

void worker() {
    std::cout << "Worker thread\n";
}

int main() {
    std::thread t(worker);
    t.join();
    std::cout << "Main thread\n";
    return 0;
}

2.6.2 互斥锁

c 复制代码
#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;
int counter = 0;

void increment() {
    for (int i = 0; i < 1000; ++i) {
        std::lock_guard<std::mutex> lock(mtx);
        ++counter;
    }
}

int main() {
    std::thread t1(increment);
    std::thread t2(increment);
    t1.join();
    t2.join();
    std::cout << "Counter: " << counter << std::endl;  // 2000
    return 0;
}
  • 应用:libuv 线程池,Node.js Worker Threads。

2.7 核心概念六:异常处理

c 复制代码
#include <iostream>
#include <stdexcept>

double divide(double a, double b) {
    if (b == 0) {
        throw std::runtime_error("Division by zero!");
    }
    return a / b;
}

int main() {
    try {
        std::cout << divide(10, 0) << std::endl;
    } catch (const std::runtime_error& e) {
        std::cout << "Error: " << e.what() << std::endl;
    }
    return 0;
}
  • 应用 :V8 的 v8::TryCatch,N-API 错误传递。

2.8 核心概念七:STL

2.8.1 容器

c 复制代码
#include <iostream>
#include <vector>
#include <map>
#include <string>

int main() {
    std::vector<int> vec = {1, 2, 3};
    vec.push_back(4);
    for (int x : vec) {
        std::cout << x << " ";  // 1 2 3 4
    }
    std::cout << std::endl;

    std::map<std::string, int> scores;
    scores["Alice"] = 90;
    scores["Bob"] = 85;
    for (const auto& pair : scores) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }
    return 0;
}

2.8.2 算法

c 复制代码
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec = {4, 2, 5, 1, 3};
    std::sort(vec.begin(), vec.end());
    for (int x : vec) {
        std::cout << x << " ";  // 1 2 3 4 5
    }
    auto it = std::find(vec.begin(), vec.end(), 3);
    if (it != vec.end()) {
        std::cout << "\nFound: " << *it << std::endl;
    }
    return 0;
}
  • 应用 :V8 用 std::vector 存储属性,libuv 用容器管理回调。

3. C++ 包管理器与 V8/libuv 安装

3.1 C++ 包管理器

3.1.1 vcpkg

  • 功能:微软跨平台 C++ 库管理器。

  • 安装

    bash 复制代码
    git clone https://github.com/microsoft/vcpkg.git
    cd vcpkg
    ./bootstrap-vcpkg.sh  # Linux/macOS
    .\bootstrap-vcpkg.bat # Windows
    ./vcpkg integrate install

3.1.2 Conan

  • 功能:跨平台 C++ 包管理器,支持二进制分发。
  • 安装pip install conan.

3.1.3 系统包管理器

  • Linux:apt, yum, pacman.
  • macOS:brew install <package>.
  • Windows:推荐 vcpkg/Conan。

3.2 安装 V8

3.2.1 vcpkg

复制代码
vcpkg install v8
  • CMake 集成:find_package(V8).

3.2.2 手动编译

bash 复制代码
git clone https://chromium.googlesource.com/v8/v8.git
cd v8
git checkout <version>
tools/dev/v8gen.py x64.release
ninja -C out.gn/x64.release

3.3 安装 libuv

3.3.1 vcpkg

复制代码
vcpkg install libuv

3.3.2 系统包管理器

  • Ubuntu:sudo apt install libuv1-dev
  • macOS:brew install libuv

3.3.3 手动编译

bash 复制代码
git clone https://github.com/libuv/libuv.git
cd libuv
mkdir build && cd build
cmake .. -DBUILD_TESTING=OFF
make && make install

3.4 编译示例程序

V8 示例

执行 JS 代码:

rust 复制代码
#include <v8.h>
#include <libplatform/libplatform.h>
#include <iostream>

int main() {
    v8::V8::InitializeICU();
    auto platform = v8::platform::NewDefaultPlatform();
    v8::V8::InitializePlatform(platform.get());
    v8::V8::Initialize();

    v8::Isolate::CreateParams create_params;
    create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
    v8::Isolate* isolate = v8::Isolate::New(create_params);

    {
        v8::Isolate::Scope isolate_scope(isolate);
        v8::HandleScope handle_scope(isolate);
        v8::Local<v8::Context> context = v8::Context::New(isolate);
        v8::Context::Scope context_scope(context);

        v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, "'Hello, V8!'").ToLocalChecked();
        v8::Local<v8::Script> script = v8::Script::Compile(context, source).ToLocalChecked();
        v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();

        v8::String::Utf8Value utf8(isolate, result);
        std::cout << *utf8 << std::endl;  // Hello, V8!
    }

    isolate->Dispose();
    v8::V8::Dispose();
    v8::V8::DisposePlatform();
    delete create_params.array_buffer_allocator;
    return 0;
}
  • 编译g++ -I$vcpkg/installed/x64-linux/include -L$vcpkg/installed/x64-linux/lib v8_example.cpp -lv8_monolith -o v8_example.

libuv 示例(定时器)

arduino 复制代码
#include <uv.h>
#include <iostream>

void timer_cb(uv_timer_t* handle) {
    std::cout << "Timer fired!" << std::endl;
    uv_stop(handle->loop);
}

int main() {
    uv_loop_t* loop = uv_default_loop();
    uv_timer_t timer;
    uv_timer_init(loop, &timer);
    uv_timer_start(&timer, timer_cb, 1000, 0);
    uv_run(loop, UV_RUN_DEFAULT);
    uv_loop_close(loop);
    return 0;
}
  • 编译g++ -I$vcpkg/installed/x64-linux/include -L$vcpkg/installed/x64-linux/lib libuv_timer.cpp -luv -o libuv_timer.

libuv 示例:简单的异步 Web 服务器

以下是一个使用 libuv 实现简单异步 HTTP 服务器的示例。它基于事件循环监听 TCP 连接,接收请求后返回固定 HTTP 响应("Hello World!"),展示 libuv 的异步非阻塞 I/O 能力。

arduino 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <uv.h>

#define DEFAULT_PORT 7000
#define DEFAULT_BACKLOG 128

uv_loop_t *loop;

void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
    buf->base = (char*) malloc(suggested_size);
    buf->len = suggested_size;
}

void on_close(uv_handle_t *handle) {
    free(handle);
}

void echo_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) {
    if (nread < 0) {
        if (nread != UV_EOF) {
            fprintf(stderr, "Read error %s\n", uv_err_name(nread));
        }
        uv_close((uv_handle_t*) client, on_close);
        free(buf->base);
        return;
    }

    // 简单返回 HTTP 响应,忽略请求内容
    const char *response = "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World!";
    uv_write_t *req = (uv_write_t *) malloc(sizeof(uv_write_t));
    uv_buf_t wrbuf = uv_buf_init((char*)response, strlen(response));
    uv_write(req, client, &wrbuf, 1, NULL);

    uv_close((uv_handle_t*) client, on_close);  // 处理完关闭连接
    free(buf->base);
}

void on_new_connection(uv_stream_t *server, int status) {
    if (status < 0) {
        fprintf(stderr, "New connection error %s\n", uv_strerror(status));
        return;
    }

    uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
    uv_tcp_init(loop, client);
    if (uv_accept(server, (uv_stream_t*) client) == 0) {
        uv_read_start((uv_stream_t*) client, alloc_buffer, echo_read);
    } else {
        uv_close((uv_handle_t*) client, on_close);
    }
}

int main() {
    loop = uv_default_loop();

    uv_tcp_t server;
    uv_tcp_init(loop, &server);

    struct sockaddr_in addr;
    uv_ip4_addr("0.0.0.0", DEFAULT_PORT, &addr);

    uv_tcp_bind(&server, (const struct sockaddr*)&addr, 0);
    int r = uv_listen((uv_stream_t*) &server, DEFAULT_BACKLOG, on_new_connection);
    if (r) {
        fprintf(stderr, "Listen error %s\n", uv_strerror(r));
        return 1;
    }

    printf("Server listening on port %d\n", DEFAULT_PORT);
    return uv_run(loop, UV_RUN_DEFAULT);
}
  • 说明:服务器监听 7000 端口,接受连接后读取数据,并返回简单 HTTP 响应。使用 libuv 的事件循环实现异步处理,支持并发连接而非阻塞。
  • 编译g++ -I$vcpkg/installed/x64-linux/include -L$vcpkg/installed/x64-linux/lib libuv_http_server.cpp -luv -o libuv_http_server.
  • 运行./libuv_http_server,然后用浏览器访问 http://localhost:7000 测试。

总结

本文介绍了 Node.js 的底层组成(V8、libuv 等)、C++ 核心概念(新增面向对象编程能力)、C++ 包管理器及 V8/libuv 安装方法,并使用 libuv 实现简单异步 Web 服务器的示例。

相关推荐
记得坚持2 小时前
vue2插槽
前端·vue.js
臣臣臣臣臣什么臣2 小时前
uni-app 多文件上传:直接循环调用 uni.uploadFile 实现(并行 / 串行双模式)
android·前端
aiopencode2 小时前
Charles 抓包 HTTPS 原理详解,从 CONNECT 到 SSL Proxying、常见问题与真机调试实战(含 Sniffmaster 补充方案)
后端
带只拖鞋去流浪2 小时前
Vue.js响应式API
前端·javascript·vue.js
泉城老铁2 小时前
springboot 框架集成工作流的开源框架有哪些呢
spring boot·后端·工作流引擎
Coder_R2 小时前
如何 把 Mac 上的 APK(app) 安装到安卓手机上?
前端·面试
aloha_2 小时前
Ubuntu/Debian 系统中,通过包管理工具安装 Redis
后端
前端小灰狼2 小时前
Ant Design Vue Vue3 table 表头筛选重置不清空Bug
前端·javascript·vue.js·bug
前端付豪2 小时前
11、JavaScript 语法:到底要不要写分号?一文吃透 ASI 与坑点清单
前端·javascript