2.4 Vector<T> 动态数组(随机访问迭代器)
C++自学精简教程 目录(必读)
该 Vector 版本特点
这里的版本主要是使用模板实现、支持随机访问迭代器,支持std::sort等所有STL算法。(本文对随机迭代器的支持参考了 复旦大学 大一公共基础课C++语言的一次作业)
随机访问迭代器的实现主要是继承std::iterator<std::random_access_iterator_tag, T>来实现的。
随机访问迭代器最牛逼的两个接口是:
friend iterator operator+(const iterator& lhs, size_t n);
friend iterator operator-(const iterator& lhs, size_t n);
问题解答
1 为何下面代码中的iterator是struct而不是class?
答:参考struct与class
题目代码
头文件 Vector.h :
#ifndef VEC_H
#define VEC_H
#include <iostream>
#include <cassert>
#include <initializer_list>
//------下面的代码是用来测试你的代码有没有问题的辅助代码,你无需关注------
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
struct Record { Record(void* ptr1, size_t count1, const char* location1, int line1, bool is) :ptr(ptr1), count(count1), line(line1), is_array(is) { int i = 0; while ((location[i] = location1[i]) && i < 100) { ++i; } }void* ptr; size_t count; char location[100] = { 0 }; int line; bool is_array = false; bool not_use_right_delete = false; }; bool operator==(const Record& lhs, const Record& rhs) { return lhs.ptr == rhs.ptr; }std::vector<Record> myAllocStatistic; void* newFunctionImpl(std::size_t sz, char const* file, int line, bool is) { void* ptr = std::malloc(sz); myAllocStatistic.push_back({ ptr,sz, file, line , is }); return ptr; }void* operator new(std::size_t sz, char const* file, int line) { return newFunctionImpl(sz, file, line, false); }void* operator new [](std::size_t sz, char const* file, int line)
{return newFunctionImpl(sz, file, line, true);
}void operator delete(void* ptr) noexcept { Record item{ ptr, 0, "", 0, false }; auto itr = std::find(myAllocStatistic.begin(), myAllocStatistic.end(), item); if (itr != myAllocStatistic.end()) { auto ind = std::distance(myAllocStatistic.begin(), itr); myAllocStatistic[ind].ptr = nullptr; if (itr->is_array) { myAllocStatistic[ind].not_use_right_delete = true; } else { myAllocStatistic[ind].count = 0; }std::free(ptr); } }void operator delete[](void* ptr) noexcept { Record item{ ptr, 0, "", 0, true }; auto itr = std::find(myAllocStatistic.begin(), myAllocStatistic.end(), item); if (itr != myAllocStatistic.end()) { auto ind = std::distance(myAllocStatistic.begin(), itr); myAllocStatistic[ind].ptr = nullptr; if (!itr->is_array) { myAllocStatistic[ind].not_use_right_delete = true; } else { myAllocStatistic[ind].count = 0; }std::free(ptr); } }
#define new new(__FILE__, __LINE__)
struct MyStruct { void ReportMemoryLeak() { std::cout << "Memory leak report: " << std::endl; bool leak = false; for (auto& i : myAllocStatistic) { if (i.count != 0) { leak = true; std::cout << "leak count " << i.count << " Byte" << ", file " << i.location << ", line " << i.line; if (i.not_use_right_delete) { cout << ", not use right delete. "; } cout << std::endl; } }if (!leak) { cout << "No memory leak." << endl; } }~MyStruct() { ReportMemoryLeak(); } }; static MyStruct my; void check_do(bool b, int line = __LINE__) { if (b) { cout << "line:" << line << " Pass" << endl; } else { cout << "line:" << line << " Ohh! not passed!!!!!!!!!!!!!!!!!!!!!!!!!!!" << " " << endl; exit(0); } }
#define check(msg) check_do(msg, __LINE__);
//------上面的代码是用来测试你的代码有没有问题的辅助代码,你无需关注------template<typename T>
class Vector
{
public:/* 提供默认构造函数, 否则只能使用有参版本,这会带来不变例如,Vector<int> arr; 这样会报错,因为需要默认构造函数*/Vector(void);//如果类提供了非默认构造函数,编译器不会自动提供默认构造函数Vector(const Vector& from);// 复制构造函数Vector(T* start, T* end);// 非默认构造函数Vector(int count, int value);//2 非默认构造函数Vector(std::initializer_list<T> value_array){for (auto& item : value_array){push_back(item);}}Vector& operator = (const Vector& from);bool operator==(const Vector& other) const{//(1) your codereturn false;}//赋值操作符~Vector();//析构函数
public:size_t size(void) const;bool empty(void) const;T& operator[] (size_t n) const;T& operator[] (size_t n);void push_back(const T& val);void clear(void);
private:void deep_copy_from(const Vector<T>& from);public:struct iterator : std::iterator<std::random_access_iterator_tag, T>{friend class Vector;friend bool operator == (const iterator& lhs, const iterator& rhs) { return lhs.m_hold == rhs.m_hold; }friend bool operator != (const iterator& lhs, const iterator& rhs) { return !(lhs == rhs); }friend size_t operator - (const iterator& lhs, const iterator& rhs) { return lhs.m_hold - rhs.m_hold; }friend bool operator < (const iterator& lhs, const iterator& rhs) { return lhs.m_hold < rhs.m_hold; }friend bool operator > (const iterator& lhs, const iterator& rhs) { return lhs.m_hold > rhs.m_hold; }friend bool operator <= (const iterator& lhs, const iterator& rhs) { return !(lhs > rhs); }friend bool operator >= (const iterator& lhs, const iterator& rhs) { return !(lhs < rhs); }friend iterator operator + (const iterator& lhs, size_t n) { iterator itr; itr.m_hold = lhs.m_hold + n; return itr; }//随机访问迭代器牛逼的地方friend iterator operator - (const iterator& lhs, size_t n) { iterator itr; itr.m_hold = lhs.m_hold - n; return itr; }//随机访问迭代器牛逼的地方public://用于前置形式iterator& operator++() { m_hold = m_hold + 1; return *this; };iterator& operator--() { m_hold = m_hold - 1; return *this; };//用于后置形式iterator operator++(int) { iterator itr = *this; m_hold += 1; return itr; }iterator operator--(int) { iterator itr = *this; m_hold -= 1; return itr; }T& operator*() const//这里必须是const in C++14{return *m_hold;}private:T* m_hold;};struct const_iterator : std::iterator<std::random_access_iterator_tag, T>{friend class Vector;friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) { return lhs.m_hold == rhs.m_hold; }friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) { return !(lhs == rhs); }friend size_t operator - (const const_iterator& lhs, const const_iterator& rhs) { return lhs.m_hold - rhs.m_hold; }friend bool operator < (const const_iterator& lhs, const const_iterator& rhs) { return lhs.m_hold < rhs.m_hold; }friend bool operator > (const const_iterator& lhs, const const_iterator& rhs) { return lhs.m_hold > rhs.m_hold; }friend bool operator <= (const const_iterator& lhs, const const_iterator& rhs) { return !(lhs > rhs); }friend bool operator >= (const const_iterator& lhs, const const_iterator& rhs) { return !(lhs < rhs); }friend const_iterator operator + (const const_iterator& lhs, size_t n) { const_iterator itr; itr.m_hold = lhs.m_hold + n; return itr; }//随机访问迭代器牛逼的地方friend const_iterator operator - (const const_iterator& lhs, size_t n) { const_iterator itr; itr.m_hold = lhs.m_hold - n; return itr; }//随机访问迭代器牛逼的地方public://用于前置形式const_iterator& operator++() { m_hold = m_hold + 1; return *this; };const_iterator& operator--() { m_hold = m_hold - 1; return *this; };//用于后置形式const_iterator operator++(int) { const_iterator itr = *this; m_hold += 1; return itr; }const_iterator operator--(int) { const_iterator itr = *this; m_hold -= 1; return itr; }const T& operator*() const{return *m_hold;}private:T* m_hold;};iterator begin() noexcept{iterator itr;itr.m_hold = empty() ? nullptr : &m_data[0];return itr;}const_iterator cbegin() const noexcept;iterator end() noexcept{iterator itr;itr.m_hold = empty() ? nullptr : &m_data[m_size];return itr;}const_iterator cend() const noexcept;
private:size_t m_size = 0;//当前元素数量size_t m_capacity = 0;//容量T* m_data = nullptr;//数据部分
};template<typename T>
Vector<T>::Vector(void)
{
}template<typename T>
Vector<T>::Vector(T * start, T * end)
{std::cout << "Vector(T* start, T* end)" << std::endl;assert(start != nullptr && end != nullptr);m_capacity = m_size = ((size_t)end - (size_t)start)/sizeof(T);//这里如果用int来存放可能会盛不下,size_t可以保证盛放的下assert(m_size > 0);m_data = new T[m_size];for (size_t i = 0; i < m_size; i++){m_data[i] = *start++;}
}
template<typename T>
Vector<T>::Vector(int count, int value)
{std::cout << "Vector(count, value)" << std::endl;if (count <= 0){throw std::runtime_error("size of vector to init must bigger than zero!");}m_data = new T[count];for (size_t i = 0; i < count; i++){m_data[i] = value;}m_capacity = m_size = count;
}
template<typename T>
Vector<T>& Vector<T>::operator=(const Vector<T>& from)
{std::cout << "Vector::operator=" << std::endl;if (this == &from){return *this;}//先释放自己的数据clear();deep_copy_from(from);return *this;
}template<typename T>
Vector<T>::~Vector()
{//(2) your code}
template<typename T>
size_t Vector<T>::size(void) const
{return m_size;
}
template<typename T>
bool Vector<T>::empty(void) const
{//(3) your codereturn false;//此处需要修改。
}
template<typename T>
T& Vector<T>::operator[](size_t n) const
{//(4) your codestatic T t;//此处需要修改。return t;//此处需要修改。
}
template<typename T>
T& Vector<T>::operator[](size_t n)
{//(4) your codestatic T t;//此处需要修改。return t;//此处需要修改。
}
template<typename T>
void Vector<T>::push_back(const T & val)
{//(5) your code// 这里需要考虑第一次插入数据的时候还没有开辟任何动态空间的情况,因为构造函数不再负责事先开辟好少量的初始预留空间了
}template<typename T>
void Vector<T>::clear(void)
{//(6) your code
}template<typename T>
void Vector<T>::deep_copy_from(const Vector<T>& from)
{//(7) your code}template<typename T>
Vector<T>::Vector(const Vector& from)
{//(8) your code}template<typename T>
typename Vector<T>::const_iterator Vector<T>::cend() const noexcept
{Vector<T>::const_iterator itr;//(9) your codereturn itr;
}template<typename T>
typename Vector<T>::const_iterator Vector<T>::cbegin() const noexcept
{const_iterator itr;//(10) your codereturn itr;
}#endif
测试代码main.cpp:
#include <iostream>
#include <algorithm>
#include "Vector.h"
#include <vector>template<typename T>
void print(const Vector<T>& v, const std::string& msg)
{std::cout << "The contents of " << msg.c_str() << " are:";for (int i = 0; i < v.size(); ++i){std::cout << ' ' << v[i];}std::cout << '\n';
}
template<typename T>
void print_itr(Vector<T>& v, const std::string& msg)
{std::cout << "The contents of " << msg.c_str() << " are:";for (auto itr = v.begin(); itr != v.end(); ++itr){std::cout << ' ' << *itr;}std::cout << '\n';
}
template<typename T>
void print_const_itr(const Vector<T>& v, const std::string& msg)
{std::cout << "The contents of " << msg.c_str() << " are:";for (auto itr = v.cbegin(); itr != v.cend(); ++itr){std::cout << ' ' << *itr;}std::cout << '\n';
}int main()
{Vector<int> a;Vector<int> first; // empty vector of intscheck(first.empty() == true && first.size() == 0);Vector<int> second(4, 100); // four ints with value 100check(second.empty() == false);check(second.size() == 4);check(*second.begin() == 100);Vector<int> fourth(second); // a copy of thirdcheck(fourth.size() == second.size());int myints[] = { 16,2,77,29 };Vector<int> fifth(myints, myints + sizeof(myints) / sizeof(int));check(fifth.empty() == false);check(fifth[0] == 16);check(fifth[3] == 29);check(fifth.size() == sizeof(myints) / sizeof(int));print(fifth, "fifth");//The contents of fifth are:16 2 77 29 fifth.push_back(30);check(fifth[4] == 30);check(fifth.size() == 5);print(fifth, "fifth");//The contents of fifth are:16 2 77 29 30 check(fifth.size() == sizeof(myints) / sizeof(int) + 1);first = fifth = fifth;print(first, "first");//The contents of first are:16 2 77 29 30 check(first.empty() == false && first.size() == fifth.size());print_itr(fifth, "fifth");//The contents of fifth are:16 2 77 29 30 print_const_itr(fifth, "fifth");//The contents of fifth are:16 2 77 29 30 std::sort(fifth.begin(), fifth.end());std::cout << "fifith after sort:" << std::endl;print_const_itr(fifth, "fifth");//The contents of fifth are:16 2 77 29 30 Vector<int> a1(myints, myints + sizeof(myints) / sizeof(int));{Vector<int> b(a1);b.push_back(2);check(b[4] == 2);auto result = (b == Vector<int>{ 16, 2, 77, 29, 2});check(result);//iteratorcheck(b.begin() + b.size() == b.end());auto begin = b.begin();auto itr = b.begin() + 1;check(*begin == 16);check(*itr == 2);}{Vector<int> b{ 1,3,5,7 };b.push_back(9);}{Vector<int> c;for (auto i : c){std::cout << i << " ";}c = a1;for (auto i : c){std::cout << i << " ";}std::cout << std::endl;}check(a1.size() == sizeof(myints) / sizeof(int));{Vector<int> c;c = fifth;c[0] = 1;check(c[0] == 1);}
}
预期输出
line:42 Pass
Vector(count, value)
line:44 Pass
line:45 Pass
line:46 Pass
line:48 Pass
Vector(T* start, T* end)
line:52 Pass
line:53 Pass
line:54 Pass
line:55 Pass
The contents of fifth are: 16 2 77 29
line:58 Pass
line:59 Pass
The contents of fifth are: 16 2 77 29 30
line:61 Pass
Vector::operator=
Vector::operator=
The contents of first are: 16 2 77 29 30
line:64 Pass
The contents of fifth are: 16 2 77 29 30
The contents of fifth are: 16 2 77 29 30
fifith after sort:
The contents of fifth are: 2 16 29 30 77
Vector(T* start, T* end)
line:74 Pass
line:76 Pass
Vector::operator=
16 2 77 29
line:95 Pass
Vector::operator=
line:100 Pass
Memory leak report:
No memory leak.
相关文章:
2.4 Vector<T> 动态数组(随机访问迭代器)
C自学精简教程 目录(必读) 该 Vector 版本特点 这里的版本主要是使用模板实现、支持随机访问迭代器,支持std::sort等所有STL算法。(本文对随机迭代器的支持参考了 复旦大学 大一公共基础课C语言的一次作业) 随机访问迭代器的实现主要是继承std::iterator<std:…...
Ubuntu下运行QEMU模拟riscv64跑Debian
1.安装QEMU 下载地址: https://www.qemu.org/download/ 建议选择稳定版本,下载后解压,然后make wget https://download.qemu.org/qemu-8.0.3.tar.xz tar xjvf qemu-8.0.3.tar.xz cd qemu-8.0.3 ./configure --enable-kvm --enable-virtfs …...

移动基站ip的工作原理
原理介绍 Basic Principle 先说一下概念,大家在不使用 WIFI 网络的时候,使用手机通过运营商提供的网络进行上网的时候,目前都是在用户端使用私有IP,然后对外做 NAT 转换,这样的情况就导致大家统一使用一些 IP 段进行访…...

Kubernetes技术--使用kubeadm搭建高可用的K8s集群(贴近实际环境)
1.高可用k8s集群架构(多master) 2.安装硬件要求 一台或多台机器,操作系统 CentOS7.x-86_x64 硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多 注: 这里属于教学环境,所以使用三台虚拟机模拟实现。 3.部署规划 4.部署前准备 (1).关闭防火墙 systemctl stop fi…...

【Linux】文件
Linux 文件 什么叫文件C语言视角下文件的操作文件的打开与关闭文件的写操作文件的读操作 & cat命令模拟实现 文件操作的系统接口open & closewriteread 文件描述符进程与文件的关系重定向问题Linux下一切皆文件的认识文件缓冲区缓冲区的刷新策略 stuout & stderr 什…...

Android OTA 相关工具(六) 使用 lpmake 打包生成 super.img
我在 《Android 动态分区详解(二) 核心模块和相关工具介绍》 介绍过 lpmake 工具,这款工具用于将多个分区镜像打包生成一个 Android 专用的动态分区镜像,一般称为 super.img。Android 编译时,系统会自动调用 lpmake 并传入相关参数来生成 sup…...
信创环境 Phytium S2500 虚拟机最大内存规格测试
在 ARM 架构中,"IPA" 通常指的是 "Instruction Set Architecture"(指令集架构),arm环境的虚拟机支持的最大内存规格与母机上内存多少无关,由arm本身的ipa size决定,ipa size 可以理解为虚拟机的物理地址空间,kernel5.4.32中ipa默认是44bits(16T si…...

新建工程——第一个S32DS工程
之前的"测试开发板"章节 测试开发板——第一个AutoSAR程序,使用了一个 demo 工程,不管是裸机程序还是 AutoSAR 程序,那都是别人已经创建好的工程。本节来介绍如何来创建自己的工程,本节介绍如何创建一个 S32DS 的工程,点亮开发板上的 LED 我们从官方提供的例程…...

基于Open3D的点云处理16-特征点匹配
点云配准 将点云数据统一到一个世界坐标系的过程称之为点云配准或者点云拼接。(registration/align) 点云配准的过程其实就是找到同名点对;即找到在点云中处在真实世界同一位置的点。 常见的点云配准算法: ICP、Color ICP、Trimed-ICP 算法…...

设计模式—简单工厂
目录 一、前言 二、简单工厂模式 1、计算器例子 2、优化后版本 3、结合面向对象进行优化(封装) 3.1、Operation运算类 3.2、客户端 4、利用面向对象三大特性(继承和多态) 4.1、Operation类 4.2、加法类 4.3、减法类 4…...

真机安装Linux Centos7
准备工具: 8G左右U盘最新版UltraISOCentOS7光盘镜像 操作步骤 下载镜像 地址:http://isoredirect.centos.org/centos/7/isos/x86_64/ 安装刻录工具UltraISO,刻录镜像到U盘 ① 选择ISO镜像文件 ② 写入磁盘镜像,在这里选择你的U盘…...

ceph peering机制-状态机
本章介绍ceph中比较复杂的模块: Peering机制。该过程保障PG内各个副本之间数据的一致性,并实现PG的各种状态的维护和转换。本章首先介绍boost库的statechart状态机基本知识,Ceph使用它来管理PG的状态转换。其次介绍PG的创建过程以及相应的状…...
Java | File类
目录: File类File类中常用的方法:boolean exists( ) :判断此 文件/目录 是否存在boolean createNewFile( ) :创建一个文件boolean mkdir( ) :创建 “单层” 目录/文件夹boolean mkdirs( ) :创建 “多层” 目…...
数学建模之灰色预测
灰色预测(Grey Forecasting)是一种用于时间序列数据分析和预测的方法,通常用于处理具有较少历史数据的情况或者数据不够充分的情况。它是一种非常简单但有效的方法,基于灰色系统理论,用来估计未来的趋势。 以下是灰色…...
03_nodejd_npm install报错
npm install报错 npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: 5kcrm11.0.0 npm ERR! Found: vue2.5.17 npm ERR! node_modules/vue npm ERR! vue"2.5.17" from the root project npm ERR! np…...

three.js(二):webpack + three.js + ts
用webpackts 开发 three.js 项目 webpack 依旧是主流的模块打包工具;ts和three.js 是绝配,three.js本身就是用ts写的,ts可以为three 项目提前做好规则约束,使项目的开发更加顺畅。 1.创建一个目录,初始化 npm mkdir demo cd de…...

最小二乘法处理线性回归
最小二乘法是一种数学优化技术,用于查找最适合一组数据点的函数。 该方法主要用于线性回归分析,当然,也可用于非线性问题。 开始之前,我们先理解一下什么是回归。 回归:回归是一种监督学习算法,用于建模和…...
ModbusCRC16校验 示例代码
作者: Herman Ye Galbot Auromix 测试环境: Ubuntu20.04 更新日期: 2023/08/30 注1: Auromix 是一个机器人爱好者开源组织。 注2: 本文在更新日期经过测试,确认有效。 笔者出于学习交流目的, 给…...

一不留神就掉坑
乘除顺序问题 在据卡特兰数[1]公式,解决leetcode-96 不同的二叉搜索树[2]时,遇到一个非常诡异的问题, package mainimport "fmt"func main() { for i : 0; i < 40; i { fmt.Printf("第%d个卡特兰数为:%d\n", i, numTrees(i)) }}func numTrees(n int) i…...

Redis数据类型(list\set\zset)
"maybe its why" List类型 列表类型是⽤来存储多个有序的字符串,列表中的每个字符串称为元素(element),⼀个列表最多可以存储个2^32 - 1个元素。在Redis中,可以对列表两端插⼊(push)…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...

如何做好一份技术文档?从规划到实践的完整指南
如何做好一份技术文档?从规划到实践的完整指南 🌟 嗨,我是IRpickstars! 🌌 总有一行代码,能点亮万千星辰。 🔍 在技术的宇宙中,我愿做永不停歇的探索者。 ✨ 用代码丈量世界&…...
第22节 Node.js JXcore 打包
Node.js是一个开放源代码、跨平台的、用于服务器端和网络应用的运行环境。 JXcore是一个支持多线程的 Node.js 发行版本,基本不需要对你现有的代码做任何改动就可以直接线程安全地以多线程运行。 本文主要介绍JXcore的打包功能。 JXcore 安装 下载JXcore安装包&a…...