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

Opengl常用缓冲对象功能介绍及使用示例(C++实现)

本文整理了常用的opengl缓冲区对象并安排了使用示例

名称英文全称作用简述
顶点数组对象Vertex Array Object (VAO)管理 VBO 和 EBO 的配置,存储顶点属性设置,简化渲染流程,避免重复设置状态
顶点缓冲区对象Vertex Buffer Object (VBO)存储顶点属性数据,提升渲染性能
索引缓冲区对象Element/Index Buffer Object (EBO/IBO)存储顶点索引,减少数据冗余
统一缓冲区对象Uniform Buffer Object (UBO)存储着色器统一变量,方便多着色器共享
着色器存储缓冲区对象Shader Storage Buffer Object (SSBO)供着色器直接读写复杂数据
像素缓冲区对象Pixel Buffer Object (PBO)加速像素数据在 CPU 和 GPU 间传输
变换反馈缓冲区对象Transform Feedback Buffer Object (TFBO)存储处理后的顶点数据用于后续渲染
原子计数器缓冲区对象Atomic Counter Buffer Object (ACBO)存储可并发修改的计数器
纹理缓冲区对象Texture Buffer Object (TBO)将缓冲区数据作为一维纹理采样
查询对象Query Object查询 OpenGL 操作状态和结果用于调试
帧缓冲区对象Framebuffer Object (FBO)自定义渲染目标实现离屏渲染
渲染缓冲区对象Renderbuffer Object (RBO)与 FBO 配合存储单一图像数据
命令缓冲区Command Buffer提前记录命令,减少 CPU - GPU 同步开销
稀疏纹理Sparse Texture仅为纹理实际部分分配内存,节省空间
采样器缓冲区对象Sampler Buffer Object结合缓冲区与采样器功能访问数据
多视图帧缓冲区对象Multiview Framebuffer Object支持同时渲染到多个视图用于特殊渲染

1. 顶点数组对象(Vertex Array Object, VAO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    // 初始化 GLFW
    if (!glfwInit()) {
        std::cerr << "GLFW 初始化失败" << std::endl;
        return -1;
    }

    // 创建窗口
    GLFWwindow* window = glfwCreateWindow(800, 600, "VAO 示例", nullptr, nullptr);
    if (!window) {
        glfwTerminate();
        std::cerr << "窗口创建失败" << std::endl;
        return -1;
    }
    glfwMakeContextCurrent(window);

    // 初始化 GLEW
    if (glewInit() != GLEW_OK) {
        glfwTerminate();
        std::cerr << "GLEW 初始化失败" << std::endl;
        return -1;
    }

    // 创建 VAO
    GLuint VAO;
    glGenVertexArrays(1, &VAO);
    // 绑定 VAO
    glBindVertexArray(VAO);

    // 这里可以进行 VBO 和 EBO 的绑定与设置

    // 解绑 VAO
    glBindVertexArray(0);

    // 主循环
    while (!glfwWindowShouldClose(window)) {
        // 处理事件
        glfwPollEvents();

        // 绑定 VAO
        glBindVertexArray(VAO);
        // 绘制操作
        // glDrawArrays(GL_TRIANGLES, 0, 3);
        // 解绑 VAO
        glBindVertexArray(0);

        // 交换缓冲区
        glfwSwapBuffers(window);
    }

    // 清理 VAO
    glDeleteVertexArrays(1, &VAO);

    // 终止 GLFW
    glfwTerminate();
    return 0;
}

2. 顶点缓冲区对象(Vertex Buffer Object, VBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "VBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 顶点数据
    float vertices[] = {
        -0.5f, -0.5f, 0.0f,
         0.5f, -0.5f, 0.0f,
         0.0f,  0.5f, 0.0f
    };

    // 创建 VBO
    GLuint VBO;
    glGenBuffers(1, &VBO);
    // 绑定 VBO
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    // 填充数据
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // 解绑 VBO
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glfwTerminate();
    // 清理 VBO
    glDeleteBuffers(1, &VBO);
    return 0;
}

3. 索引缓冲区对象(Element Buffer Object, EBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "EBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 顶点数据
    float vertices[] = {
        -0.5f, -0.5f, 0.0f,
         0.5f, -0.5f, 0.0f,
         0.0f,  0.5f, 0.0f
    };
    // 索引数据
    unsigned int indices[] = {
        0, 1, 2
    };

    // 创建 EBO
    GLuint EBO;
    glGenBuffers(1, &EBO);
    // 绑定 EBO
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    // 填充数据
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    // 解绑 EBO
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    glfwTerminate();
    // 清理 EBO
    glDeleteBuffers(1, &EBO);
    return 0;
}

4. 统一缓冲区对象(Uniform Buffer Object, UBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

const GLuint UBO_BINDING_POINT = 0;

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "UBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 创建 UBO
    GLuint UBO;
    glGenBuffers(1, &UBO);
    // 绑定 UBO
    glBindBuffer(GL_UNIFORM_BUFFER, UBO);
    // 分配内存
    glBufferData(GL_UNIFORM_BUFFER, 16 * sizeof(float), nullptr, GL_STATIC_DRAW);
    // 绑定到指定绑定点
    glBindBufferBase(GL_UNIFORM_BUFFER, UBO_BINDING_POINT, UBO);

    // 解绑 UBO
    glBindBuffer(GL_UNIFORM_BUFFER, 0);

    glfwTerminate();
    // 清理 UBO
    glDeleteBuffers(1, &UBO);
    return 0;
}

5. 着色器存储缓冲区对象(Shader Storage Buffer Object, SSBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "SSBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 数据
    float data[] = {1.0f, 2.0f, 3.0f, 4.0f};

    // 创建 SSBO
    GLuint SSBO;
    glGenBuffers(1, &SSBO);
    // 绑定 SSBO
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO);
    // 填充数据
    glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
    // 绑定到指定绑定点
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, SSBO);

    // 解绑 SSBO
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);

    glfwTerminate();
    // 清理 SSBO
    glDeleteBuffers(1, &SSBO);
    return 0;
}

6. 像素缓冲区对象(Pixel Buffer Object, PBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "PBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 创建 PBO
    GLuint PBO;
    glGenBuffers(1, &PBO);
    // 绑定 PBO
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, PBO);
    // 分配内存
    glBufferData(GL_PIXEL_UNPACK_BUFFER, 800 * 600 * 4, nullptr, GL_STREAM_DRAW);

    // 解绑 PBO
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

    glfwTerminate();
    // 清理 PBO
    glDeleteBuffers(1, &PBO);
    return 0;
}

7. 变换反馈缓冲区对象(Transform Feedback Buffer Object, TFBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "TFBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 创建 TFBO
    GLuint TFBO;
    glGenBuffers(1, &TFBO);
    // 绑定 TFBO
    glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, TFBO);
    // 分配内存
    glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
    // 绑定到变换反馈绑定点
    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, TFBO);

    // 解绑 TFBO
    glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);

    glfwTerminate();
    // 清理 TFBO
    glDeleteBuffers(1, &TFBO);
    return 0;
}

8. 原子计数器缓冲区对象(Atomic Counter Buffer Object, ACBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "ACBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 创建 ACBO
    GLuint ACBO;
    glGenBuffers(1, &ACBO);
    // 绑定 ACBO
    glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, ACBO);
    // 分配内存
    glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), nullptr, GL_DYNAMIC_DRAW);
    // 绑定到指定绑定点
    glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, ACBO);

    // 解绑 ACBO
    glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);

    glfwTerminate();
    // 清理 ACBO
    glDeleteBuffers(1, &ACBO);
    return 0;
}

9. 纹理缓冲区对象(Texture Buffer Object, TBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "TBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 数据
    float data[] = {1.0f, 2.0f, 3.0f, 4.0f};

    // 创建 TBO
    GLuint TBO;
    glGenBuffers(1, &TBO);
    // 绑定 TBO
    glBindBuffer(GL_TEXTURE_BUFFER, TBO);
    // 填充数据
    glBufferData(GL_TEXTURE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);

    // 创建纹理
    GLuint texture;
    glGenTextures(1, &texture);
    // 绑定纹理
    glBindTexture(GL_TEXTURE_BUFFER, texture);
    // 将 TBO 关联到纹理
    glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, TBO);

    // 解绑 TBO 和纹理
    glBindBuffer(GL_TEXTURE_BUFFER, 0);
    glBindTexture(GL_TEXTURE_BUFFER, 0);

    glfwTerminate();
    // 清理 TBO 和纹理
    glDeleteBuffers(1, &TBO);
    glDeleteTextures(1, &texture);
    return 0;
}

10. 查询对象(Query Object)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "查询对象示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 创建查询对象
    GLuint query;
    glGenQueries(1, &query);

    // 开始查询
    glBeginQuery(GL_SAMPLES_PASSED, query);

    // 这里进行绘制操作
    // glDrawArrays(GL_TRIANGLES, 0, 3);

    // 结束查询
    glEndQuery(GL_SAMPLES_PASSED);

    // 获取查询结果
    GLuint result;
    glGetQueryObjectuiv(query, GL_QUERY_RESULT, &result);
    std::cout << "采样通过数量: " << result << std::endl;

    // 清理查询对象
    glDeleteQueries(1, &query);

    glfwTerminate();
    return 0;
}

11. 帧缓冲区对象(Framebuffer Object, FBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "FBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 创建 FBO
    GLuint FBO;
    glGenFramebuffers(1, &FBO);
    // 绑定 FBO
    glBindFramebuffer(GL_FRAMEBUFFER, FBO);

    // 这里可以创建并附加纹理或渲染缓冲区

    // 检查 FBO 是否完整
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
        std::cerr << "FBO 不完整" << std::endl;

    // 解绑 FBO
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    glfwTerminate();
    // 清理 FBO
    glDeleteFramebuffers(1, &FBO);
    return 0;
}

12. 渲染缓冲区对象(Renderbuffer Object, RBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "RBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 创建 RBO
    GLuint RBO;
    glGenRenderbuffers(1, &RBO);
    // 绑定 RBO
    glBindRenderbuffer(GL_RENDERBUFFER, RBO);
    // 分配内存
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600);

    // 解绑 RBO
    glBindRenderbuffer(GL_RENDERBUFFER, 0);

    glfwTerminate();
    // 清理 RBO
    glDeleteRenderbuffers(1, &RBO);
    return 0;
}

13. 命令缓冲区(Command Buffer)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <vector>

// 模拟命令结构体
struct Command {
    enum Type { DRAW_ARRAYS } type;
    GLenum mode;
    GLint first;
    GLsizei count;
};

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "命令缓冲区示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    std::vector<Command> commandBuffer;

    // 添加命令到缓冲区
    Command cmd;
    cmd.type = Command::DRAW_ARRAYS;
    cmd.mode = GL_TRIANGLES;
    cmd.first = 0;
    cmd.count = 3;
    commandBuffer.push_back(cmd);

    // 执行命令缓冲区中的命令
    for (const auto& cmd : commandBuffer) {
        if (cmd.type == Command::DRAW_ARRAYS) {
            glDrawArrays(cmd.mode, cmd.first, cmd.count);
        }
    }

    glfwTerminate();
    return 0;
}

稀疏纹理(Sparse Texture)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

const int WIDTH = 800;
const int HEIGHT = 600;

int main() {
    // 初始化 GLFW
    if (!glfwInit()) {
        std::cerr << "GLFW 初始化失败" << std::endl;
        return -1;
    }

    // 创建窗口
    GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Sparse Texture Example", nullptr, nullptr);
    if (!window) {
        glfwTerminate();
        std::cerr << "窗口创建失败" << std::endl;
        return -1;
    }
    glfwMakeContextCurrent(window);

    // 初始化 GLEW
    if (glewInit() != GLEW_OK) {
        glfwTerminate();
        std::cerr << "GLEW 初始化失败" << std::endl;
        return -1;
    }

    // 检查是否支持稀疏纹理扩展
    if (!GLEW_ARB_sparse_texture) {
        std::cerr << "不支持 ARB_sparse_texture 扩展" << std::endl;
        glfwTerminate();
        return -1;
    }

    // 创建纹理对象
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);

    // 设置纹理参数
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // 分配稀疏纹理存储
    GLint alignment;
    glGetInternalformativ(GL_TEXTURE_2D, GL_RGBA8, GL_TEXTURE_SPARSE_ARB, 1, &alignment);
    glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, WIDTH, HEIGHT, GL_TRUE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SPARSE_ARB, GL_TRUE);

    // 定义一个稀疏纹理的子区域
    GLint x = 0, y = 0, z = 0;
    GLint width = WIDTH / 2, height = HEIGHT / 2, depth = 1;
    GLint level = 0;
    glTexPageCommitmentARB(GL_TEXTURE_2D, level, x, y, z, width, height, depth, GL_TRUE);

    // 主循环
    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();

        // 清屏
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // 这里可以进行纹理绘制操作

        glfwSwapBuffers(window);
    }

    // 清理资源
    glDeleteTextures(1, &texture);
    glfwTerminate();
    return 0;
}

采样器缓冲区对象(Sampler Buffer Object)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

const int WIDTH = 800;
const int HEIGHT = 600;

int main() {
    // 初始化 GLFW
    if (!glfwInit()) {
        std::cerr << "GLFW 初始化失败" << std::endl;
        return -1;
    }

    // 创建窗口
    GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Sampler Buffer Object Example", nullptr, nullptr);
    if (!window) {
        glfwTerminate();
        std::cerr << "窗口创建失败" << std::endl;
        return -1;
    }
    glfwMakeContextCurrent(window);

    // 初始化 GLEW
    if (glewInit() != GLEW_OK) {
        glfwTerminate();
        std::cerr << "GLEW 初始化失败" << std::endl;
        return -1;
    }

    // 创建缓冲区对象
    GLuint buffer;
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_TEXTURE_BUFFER, buffer);

    // 分配缓冲区数据
    const int bufferSize = 1024;
    float* data = new float[bufferSize];
    for (int i = 0; i < bufferSize; ++i) {
        data[i] = static_cast<float>(i);
    }
    glBufferData(GL_TEXTURE_BUFFER, bufferSize * sizeof(float), data, GL_STATIC_DRAW);
    delete[] data;

    // 创建纹理对象并绑定到缓冲区
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_BUFFER, texture);
    glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, buffer);

    // 主循环
    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();

        // 清屏
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // 这里可以在着色器中使用采样器缓冲区对象进行采样操作

        glfwSwapBuffers(window);
    }

    // 清理资源
    glDeleteTextures(1, &texture);
    glDeleteBuffers(1, &buffer);
    glfwTerminate();
    return 0;
}

多视图帧缓冲区对象(Multiview Framebuffer Object)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

const int WIDTH = 800;
const int HEIGHT = 600;

int main() {
    // 初始化 GLFW
    if (!glfwInit()) {
        std::cerr << "GLFW 初始化失败" << std::endl;
        return -1;
    }

    // 创建窗口
    GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Multiview Framebuffer Object Example", nullptr, nullptr);
    if (!window) {
        glfwTerminate();
        std::cerr << "窗口创建失败" << std::endl;
        return -1;
    }
    glfwMakeContextCurrent(window);

    // 初始化 GLEW
    if (glewInit() != GLEW_OK) {
        glfwTerminate();
        std::cerr << "GLEW 初始化失败" << std::endl;
        return -1;
    }

    // 检查是否支持多视图扩展
    if (!GLEW_NV_multiview) {
        std::cerr << "不支持 NV_multiview 扩展" << std::endl;
        glfwTerminate();
        return -1;
    }

    // 创建帧缓冲区对象
    GLuint fbo;
    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    // 创建纹理附件
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
    glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, WIDTH, HEIGHT, 2); // 2 个视图

    // 将纹理附件附加到帧缓冲区
    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0);

    // 设置多视图
    GLuint views[] = {0, 1};
    glNamedFramebufferMultiviewOVR(fbo, GL_COLOR_ATTACHMENT0, texture, 0, 0, 2, 2, views);

    // 主循环
    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();

        // 清屏
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // 这里可以进行多视图渲染操作

        glfwSwapBuffers(window);
    }

    // 清理资源
    glDeleteTextures(1, &texture);
    glDeleteFramebuffers(1, &fbo);
    glfwTerminate();
    return 0;
}

相关文章:

  • Qt中QRadioButton的使用
  • 钉钉快捷免登录 通过浏览器打开第三方系统,
  • element ui 组件el-autocomplete的使用方法(输入建议,利用filter和include)
  • 碳基生物的悲歌-DeepSeek思考实现Linux动态库递归收集工具
  • SpringBoot中实现限流和熔断功能
  • 算法系列之贪心算法
  • Java试题:进制转换
  • 分布式锁实现(数据库+Redis+Zookeeper)
  • redis中的Lua脚本,redis的事务机制
  • 深度学习技术文章质量提升指南(基于CSDN评分算法优化)
  • http代理IP怎么实现?如何解决代理IP访问不了问题?
  • 【nextJs】官网demo学习
  • REACT--组件通信
  • 长短期记忆网络:从理论到创新应用的深度剖析
  • 链表-基础训练(二)链表 day14
  • HAProxy介绍与编译安装
  • 宝塔扩容——阿里云如何操作
  • ‌最新版DeepSeek保姆级安装教程:本地部署+避坑指南
  • 动态规划01背包问题系列一>01背包
  • Spring Boot 如何保证接口安全
  • 西甲上海足球学院揭幕,用“足球方法论”试水中国青训
  • 105岁八路军老战士、抗美援朝老战士谭克煜逝世
  • 高盛上调A股未来12个月目标点位,沪深300指数潜在回报15%
  • 国家主席习近平同普京总统举行大范围会谈
  • 一季度全国消协组织为消费者挽回经济损失23723万元
  • 叙利亚政权领导人首访西方国家,与法国总统讨论叙局势