【linux学习指南】模拟线程封装与智能指针shared_ptr

文章目录
- 📝线程封装
- 🌉 Thread.hpp
- 🌉 Makefile
- 🌠线程封装第一版
- 🌉 Makefile:
- 🌉Main.cc
- 🌉 Thread.hpp:
- 🌠线程封装第二版
- 🌉 Thread.hpp:
- 🌉 Main.cc
- 🌠单线程创建测试
- 🌉 Thread.hpp
- 🌉 main.cc
- 🌠智能指针std::shared_ptr
- 🚩总结
📝线程封装
🌉 Thread.hpp
// Thread.hpp
#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <pthread.h>
namespace ThreadModule
{// 原⼦计数器,⽅便形成线程名称std::uint32_t cnt = 0;// 线程要执⾏的外部⽅法,我们不考虑传参,后续有std::bind 来进⾏类间耦合using threadfunc_t = std::function<void()>;// 线程状态enum class TSTATUS{THREAD_NEW,THREAD_RUNNING,THREAD_STOP};// 线程class Thread{private:static void *run(void *obj){Thread *self = static_cast<Thread *>(obj);pthread_setname_np(pthread_self(), self->_name.c_str()); // 设置线程名称self->_status = TSTATUS::THREAD_RUNNING;if (!self->_joined){pthread_detach(pthread_self());}self->_func();return nullptr;}void SetName(){// 后期加锁保护_name = "Thread-" + std::to_string(cnt++);}public:Thread(threadfunc_t func) : _status(TSTATUS::THREAD_NEW),_joined(true), _func(func){SetName();}void EnableDetach(){if (_status == TSTATUS::THREAD_NEW)_joined = false;}void EnableJoined(){if (_status == TSTATUS::THREAD_NEW)_joined = true;}bool Start(){if (_status == TSTATUS::THREAD_RUNNING)return true;int n = ::pthread_create(&_id, nullptr, run, this);if (n != 0)return false;return true;}bool Join(){if (_joined){int n = pthread_join(_id, nullptr);if (n != 0)return false;return true;}return false;}~Thread() {}private:std::string _name;pthread_t _id;TSTATUS _status;bool _joined;threadfunc_t _func;};
}
🌉 Makefile
// main.cc
#include <iostream>
#include <unistd.h>
#include "Thread.hpp"
void hello1()
{char buffer[64];pthread_getname_np(pthread_self(), buffer, sizeof(buffer) - 1);while (true){}std::cout << "hello world, " << buffer << std::endl;sleep(1);
}
void hello2()
{char buffer[64];pthread_getname_np(pthread_self(), buffer, sizeof(buffer) - 1);while (true){std::cout << "hello world, " << buffer << std::endl;sleep(1);}
}
int main()
{pthread_setname_np(pthread_self(), "main");ThreadModule::Thread t1(hello1);t1.Start();ThreadModule::Thread t2(std::bind(&hello2));t2.Start();t1.Join();t2.Join();return 0;
}
运⾏结果查询
$ ps -aLPID LWP TTY TIME CMD
195828 195828 pts/1 00:00:00 main
195828 195829 pts/1 00:00:00 Thread-0
195828 195830 pts/1 00:00:00 Thread-1
🌠线程封装第一版
🌉 Makefile:
bin=testThread
cc=g++
src=$(wildcard *.cc)
obj=$(src:.cc=.o)$(bin):$(obj)$(cc) -o $@ $^ -lpthread
%.o:%.cc$(cc) -c $< -std=c++17.PHONY:test
test:echo $(src)echo $(obj)
🌉Main.cc
#include "Thread.hpp"
#include <unordered_map>
#include <memory>// using thread_ptr_t = std::shared_ptr<ThreadModule::Thread>;#define NUM 10;class threadData
{
public:int max;int start;
};void Count(threadData td)
{for(int i = td.start; i < td.max; i++){std::cout<< "i == " <<i <<std::endl;sleep(1);}
}int main()
{threadData td;td.max = 60;td.start = 50;//使用lamda表达式封装Count成一个不接受参数的可调用对象auto func = [td](){Count(td);};ThreadModule::Thread<threadData> t(func);t.Start();t.Join();return 0;
}
🌉 Thread.hpp:
//V1
namespace ThreadModule
{// template<typename T>using func_t = std::function<void()>;static int number = 1;enum class TSTATUS{NEW,RUNNING,STOP};template<typename T>class Thread{private:static void* Routine(void *args){Thread* t = static_cast<Thread *>(args);t->_status = TSTATUS::RUNNING;t->_func();return nullptr;}void EnableDetach(){_joinable = false;}public:Thread(func_t func): _func(func), _status(TSTATUS::NEW), _joinable(true){_name = "Thread - " + std::to_string(number++);_pid = getpid();}bool Start(){if (_status != TSTATUS::RUNNING){int n = ::pthread_create(&_tid, nullptr, Routine, this); // 这里使用thisif (n != 0)return false;return true;}return true;}bool Stop(){if (_status != TSTATUS::RUNNING){int n = ::pthread_cancel(_tid);if (n != 0)return false;_status = TSTATUS::STOP; return true;}return false;}bool Join(){if(_joinable){int n = ::pthread_join(_tid, nullptr);if(n != 0)return false;_status = TSTATUS::STOP; return true; }return false;}void Detach(){EnableDetach();pthread_detach(_tid);}bool IsJoinable(){return _joinable;}std::string Name(){return _name;}~Thread(){}private:std::string _name;pthread_t _tid;pid_t _pid;bool _joinable; // 是否是分离的, 默认不是func_t _func;TSTATUS _status;};
}#endif


🌠线程封装第二版
🌉 Thread.hpp:
#ifndef THREAD_HPP
#define THREAD_HPP#include <iostream>
#include <string>
#include <pthread.h>
#include <functional>
#include <sys/types.h>
#include <unistd.h>//V2
namespace ThreadModule
{static int number = 1;enum class TSTATUS{NEW,RUNNING,STOP};template<typename T>class Thread{using func_t = std::function<void(T)>;private://成员方法static void *Routine(void* args){Thread<T> *t = static_cast<Thread<T>*>(args);t->_status = TSTATUS::RUNNING;t->_func(t->_data);return nullptr;}void EnableDetach(){_joinable = false;}public:Thread(func_t func, T data):_func(func),_data(data),_status(TSTATUS::NEW),_joinable(true){_name = "Thread -" +std::to_string(number++);_pid = getpid();}bool Start(){if(_status != TSTATUS::RUNNING){int n = pthread_create(&_tid, nullptr, Routine, this);if(n != 0)return false;return true;}return false;}bool Stop(){if(_status == TSTATUS::RUNNING){int n = ::pthread_cancel(_tid);if(n != 0)return false;_status = TSTATUS::STOP;return true;}return false;}bool Join(){if(_joinable){int n = ::pthread_join(_tid, nullptr);if(n != 0)return false;_status = TSTATUS::STOP;return true;}return false;}bool IsJoinale(){return _joinable;}std::string Name(){return _name;}~Thread(){}private:std::string _name;pthread_t _tid;bool _joinable;//是否是分离的,默认不是func_t _func;pid_t _pid;TSTATUS _status;T _data;};
}#endif
🌉 Main.cc
#include "Thread.hpp"
#include <unordered_map>
#include <memory>using thread_ptr_t = std::shared_ptr<ThreadModule::Thread<int>>;#define NUM 10class threadData
{
public:int max;int start;
};void Count(threadData td)
{for(int i = td.start; i < td.max; i++){std::cout<< "i == " <<i <<std::endl;sleep(1);}
}
int main()
{//先描述再组织std::unordered_map<std::string, thread_ptr_t> threads;//如果我们要创建多线程呢?for(int i = 0; i< NUM ; i++){auto func = [](){while(true){std::cout<< "hello world" << std::endl;sleep(1);}};int threadData = i+1; thread_ptr_t t= std::make_shared<ThreadModule::Thread<int>>([func](int){func();}, threadData);std::cout<< "Create thread with name : "<<t->Name() <<std::endl;threads[t->Name()] = t;}for(auto &thread : threads){thread.second->Start();}for(auto &thread : threads){thread.second->Join();}


🌠单线程创建测试
🌉 Thread.hpp
#ifndef THREAD_HPP
#define THREAD_HPP#include <iostream>
#include <string>
#include <pthread.h>
#include <functional>
#include <sys/types.h>
#include <unistd.h>//V2
namespace ThreadModule
{static int number = 1;enum class TSTATUS{NEW,RUNNING,STOP};template<typename T>class Thread{using func_t = std::function<void(T)>;private://成员方法static void *Routine(void* args){Thread<T> *t = static_cast<Thread<T>*>(args);t->_status = TSTATUS::RUNNING;t->_func(t->_data);return nullptr;}void EnableDetach(){_joinable = false;}public:Thread(func_t func, T data):_func(func),_data(data),_status(TSTATUS::NEW),_joinable(true){_name = "Thread -" +std::to_string(number++);_pid = getpid();}bool Start(){if(_status != TSTATUS::RUNNING){int n = pthread_create(&_tid, nullptr, Routine, this);if(n != 0)return false;return true;}return false;}bool Stop(){if(_status == TSTATUS::RUNNING){int n = ::pthread_cancel(_tid);if(n != 0)return false;_status = TSTATUS::STOP;return true;}return false;}bool Join(){if(_joinable){int n = ::pthread_join(_tid, nullptr);if(n != 0)return false;_status = TSTATUS::STOP;return true;}return false;}bool IsJoinale(){return _joinable;}std::string Name(){return _name;}~Thread(){}private:std::string _name;pthread_t _tid;bool _joinable;//是否是分离的,默认不是func_t _func;pid_t _pid;TSTATUS _status;T _data;};
}
🌉 main.cc
#include "Thread.hpp"
#include <unordered_map>
#include <memory>using thread_ptr_t = std::shared_ptr<ThreadModule::Thread<int>>;#define NUM 10class threadData
{
public:int max;int start;
};void Count(threadData td)
{for(int i = td.start; i < td.max; i++){std::cout<< "i == " <<i <<std::endl;sleep(1);}
}int main()
{auto func = [](){while(true){std::cout<< "hello world" <<std::endl;sleep(1);}};std::function<void(int)> wrappedFunc2 = [func](int){ func(); };int signalTreadData = 5;ThreadModule::Thread<int> t( wrappedFunc2,signalTreadData);// std::cout<< "Create thread with name : "<<t->Name() <<std::endl;// t.Start();// t.Join();t.Start();std::cout<< t.Name() << " is running" <<std::endl;std::cout<<std::flush;//手动刷新缓冲期sleep(5);if (t.Stop()) {std::cout << "Stop thread : " << t.Name() << std::endl;std::cout << std::flush; // 手动刷新缓冲区} else {std::cout << "Failed to stop thread : " << t.Name() << std::endl;std::cout << std::flush; // 手动刷新缓冲区}sleep(1);if (t.Join()) {std::cout << "Join thread : " << t.Name() << std::endl;std::cout << std::flush; // 手动刷新缓冲区} else {std::cout << "Failed to join thread : " << t.Name() << std::endl;std::cout << std::flush; // 手动刷新缓冲区}return 0;
}


🌠智能指针std::shared_ptr
std::shared_ptr 是 C++ 标准库 <memory> 头文件中提供的一种智能指针,用于管理动态分配的对象,它实现了共享所有权的语义,下面为你详细介绍它的作用、工作原理以及在你给出的代码中的使用场景。
作用
在传统的 C++ 中,使用 new 操作符动态分配内存后,需要手动使用 delete 操作符释放内存,否则会导致内存泄漏。std::shared_ptr 可以自动管理动态分配的对象的生命周期,当没有任何 std::shared_ptr 指向该对象时,它会自动释放对象所占用的内存,从而避免了手动管理内存带来的复杂性和潜在的内存泄漏问题。
工作原理
std::shared_ptr 使用引用计数的机制来管理对象的生命周期。每个 std::shared_ptr 都维护一个引用计数,记录有多少个 std::shared_ptr 共享同一个对象。当一个新的 std::shared_ptr 指向一个对象时,引用计数加 1;当一个 std::shared_ptr 被销毁或者指向其他对象时,引用计数减 1。当引用计数变为 0 时,说明没有任何 std::shared_ptr 再指向该对象,此时 std::shared_ptr 会自动调用对象的析构函数并释放内存。
-
using thread_ptr_t = std::shared_ptr<ThreadModule::Thread<int>>;
这行代码使用using关键字定义了一个类型别名thread_ptr_t,它实际上是std::shared_ptr<ThreadModule::Thread<int>>的别名。这样做的好处是可以简化代码,避免在后续使用时多次书写冗长的类型名。这里的ThreadModule::Thread<int>是一个模板类的实例化,表示一个线程对象,std::shared_ptr用于管理这个线程对象的生命周期。 -
std::unordered_map<std::string, thread_ptr_t> threads;
这行代码定义了一个std::unordered_map,它是一个无序关联容器,用于存储键值对。键的类型是std::string,值的类型是thread_ptr_t,也就是std::shared_ptr<ThreadModule::Thread<int>>。通过这种方式,可以将线程对象与一个字符串键关联起来,方便对线程对象进行管理和查找。 -
thread_ptr_t t = std::make_shared<ThreadModule::Thread<int>>( ... );
这行代码使用std::make_shared函数创建了一个std::shared_ptr<ThreadModule::Thread<int>>对象,并将其赋值给t。std::make_shared是一个便捷的函数,用于创建std::shared_ptr对象,它会在一次内存分配中同时分配对象和引用计数所需的内存,比分别使用new和std::shared_ptr的构造函数更加高效。括号内的参数是传递给ThreadModule::Thread<int>构造函数的参数,用于初始化线程对象。
示例代码
#include <iostream>
#include <memory>class MyClass {
public:MyClass() { std::cout << "MyClass constructor" << std::endl; }~MyClass() { std::cout << "MyClass destructor" << std::endl; }void doSomething() { std::cout << "Doing something..." << std::endl; }
};int main() {// 创建一个 std::shared_ptr 对象std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();// 复制一个 std::shared_ptr 对象,引用计数加 1std::shared_ptr<MyClass> ptr2 = ptr1;// 调用对象的成员函数ptr1->doSomething();// 当 ptr1 和 ptr2 离开作用域时,引用计数减 1// 当引用计数变为 0 时,对象会被自动销毁return 0;
}
代码解释
- 在
main函数中,首先使用std::make_shared创建了一个std::shared_ptr<MyClass>对象ptr1,此时引用计数为 1。 - 然后将
ptr1赋值给ptr2,引用计数变为 2。 - 调用
ptr1->doSomething()来调用对象的成员函数。 - 当
ptr1和ptr2离开main函数的作用域时,它们会被销毁,引用计数减 1。当引用计数变为 0 时,MyClass对象的析构函数会被自动调用,释放对象所占用的内存。
🚩总结
如果要像C++11那样进⾏可变参数的传递,是可以这样设计的,但是太⿇烦了,真到了哪⼀步,就直接⽤c++11吧,我们的⽬标主要是理解系统概念对象化,此处不做复杂设计,⽽且后续可以使⽤std::bind来进⾏对象间调⽤

相关文章:
【linux学习指南】模拟线程封装与智能指针shared_ptr
文章目录 📝线程封装🌉 Thread.hpp🌉 Makefile 🌠线程封装第一版🌉 Makefile:🌉Main.cc🌉 Thread.hpp: 🌠线程封装第二版🌉 Thread.hpp:🌉 Main.cc …...
10、Python面试题解析:解释reduce函数的工作原理
reduce 是 Python 中的一个高阶函数,位于 functools 模块中。它的作用是将一个可迭代对象(如列表、元组等)中的元素依次通过一个二元函数(即接受两个参数的函数)进行累积计算,最终返回一个单一的结果。 1.…...
【含开题报告+文档+PPT+源码】学术研究合作与科研项目管理应用的J2EE实施
开题报告 本研究构建了一套集注册登录、信息获取与科研项目管理于一体的综合型学术研究合作平台。系统用户通过注册登录后,能够便捷地接收到最新的系统公告和科研动态新闻,并能进一步点击查看详尽的新闻内容。在科研项目管理方面,系统提供强…...
MySQL主从复制过程,延迟高,解决应对策略
MySQL主从复制延迟高是常见的性能问题,通常由主库写入压力大、从库处理能力不足或配置不当导致。以下从原因定位、优化策略和高级解决方案三个维度提供系统性解决方法: 一、快速定位延迟原因 1. 查看主从同步状态 SHOW SLAVE STATUS\G关键字段…...
Deepseek模拟阿里面试——数据库
在模拟阿里面试时,数据库部分需要涵盖广泛的知识点,包括基础概念、事务管理、索引优化、数据库设计、高并发处理、分布式数据库等。以下是对这些问题的详细分析和解答: 事务的ACID特性是什么,如何保证? ACID特性&…...
大数据学习之SparkStreaming、PB级百战出行网约车项目一
一.SparkStreaming 163.SparkStreaming概述 Spark Streaming is an extension of the core Spark API that enables scalable, high-throughput, fault-tolerant stream processing of live data streams. Spark Streaming 是核心 Spark API 的扩展,支持实时数据…...
Java 高频面试闯关秘籍
目录 Java基础篇:涵盖OOP、多线程、集合等基础知识。Java高级篇:深入探讨HashMap、JVM、线程池等高级特性。Java框架篇:介绍Spring、SpringMVC、MyBatis等常用框架。Mysql数据库篇:包含SQL语句、事务、索引等数据库知识。分布式技…...
边缘计算网关驱动智慧煤矿智能升级——实时预警、低延时决策与数字孪生护航矿山安全高效运营
迈向智能化煤矿管理新时代 工业物联网和边缘计算技术的迅猛发展,煤矿安全生产与高效运营正迎来全新变革。传统煤矿监控模式由于现场环境复杂、数据采集和传输延时较高,已难以满足当下高标准的安全管理要求。为此,借助边缘计算网关的实时数据…...
Oracle认证大师(OCM)学习计划书
Oracle认证大师(OCM)学习计划书 一、学习目标 Oracle Certified Master(OCM)是Oracle官方认证体系中的最高级别认证,要求考生具备扎实的数据库管理技能、丰富的实战经验以及解决复杂问题的能力。本计划旨在通过系统化的…...
力扣 单词拆分
动态规划,字符串截取,可重复用,集合类。 题目 单词可以重复使用,一个单词可用多次,应该是比较灵活的组合形式了,可以想到用dp,遍历完单词后的状态的返回值。而这里的wordDict给出的是list&…...
如何在Linux中设置定时任务(cron)
在Linux系统中,定时任务是自动执行任务的一种非常方便的方式,常常用于定期备份数据、更新系统或清理日志文件等操作。cron是Linux下最常用的定时任务管理工具,它允许用户根据设定的时间间隔自动执行脚本和命令。在本文中,我们将详…...
C# ASP.NET核心特性介绍
.NET学习资料 .NET学习资料 .NET学习资料 在当今的软件开发领域中,C# ASP.NET凭借其强大的功能和丰富的特性,成为构建 Web 应用程序的重要技术之一。以下将详细介绍 C# ASP.NET的核心特性。 多语言支持 ASP.NET 支持多种语言进行开发,这使…...
Response 和 Request 介绍
怀旧网个人博客网站地址:怀旧网,博客详情:Response 和 Request 介绍 1、HttpServletResponse 1、简单分类 2、文件下载 通过Response下载文件数据 放一个文件到resources目录 编写下载文件Servlet文件 public class FileDownServlet exten…...
Spring常用注解和组件
引言 了解Spring常用注解的使用方式可以帮助我们更快速理解这个框架和其中的深度 注解 Configuration:表示该类是一个配置类,用于定义 Spring Bean。 EnableAutoConfiguration:启用 Spring Boot 的自动配置功能,让 Spring Boo…...
Spring中都应用了哪些设计模式?
好的!以下是您提到的八种设计模式在 Spring 中的简单示例: 1. 简单工厂模式 简单工厂模式通过传入参数来决定实例化哪个类。Spring 中的 BeanFactory 就是简单工厂模式的应用。 示例代码: // 1. 创建接口和具体实现类 public interface A…...
VSCode的安裝以及使用
c配置: 【MinGw-w64编译器套件】 https://blog.csdn.net/weixin_60915103/article/details/131617196?fromshareblogdetail&sharetypeblogdetail&sharerId131617196&sharereferPC&sharesourcem0_51662391&sharefromfrom_link Python配置: 【簡單ÿ…...
Datawhale 组队学习 Ollama教程 task1
一、Ollama 简介 比喻:Ollama 就像是一个“魔法箱子”,里面装满了各种大型语言模型(LLM)。你不需要懂复杂的魔法咒语(配置),只需要轻轻一按(一条命令),就能让…...
前端技术学习——ES6核心基础
1、ES6与JavaScript之间的关系 ES6是JavaScript的一个版本:JavaScript是基于ECMAScript规范实现的编程语言,而ES6(ECMAScript 2015)是该规范的一个具体版本。 2、ES6的基础功能 (1)let和const let用于声明…...
《DeepSeek技术应用与赋能运营商办公提效案例实操落地课程》
大模型算法实战专家—周红伟老师 法国科学院数据算法博士/曾任阿里巴巴人工智能专家/曾任马上消费企业风控负责人 课程背景 随着大模型技术的迅猛发展,企业面临着提升工作效率、降低运营成本和优化资源配置的巨大压力。DeepSeek做出十三项革命性的大模型技术突破…...
STM32-知识
一、Cortex-M系列双指针 Cortex-M系列的MSP与PSP有一些重要的区别,双指针是为了保证OS的安全性和稳健性。本质上,区别于用户程序使用PSP,操作系统和异常事件单独使用一个MSP指针的目的,是为了保证栈数据不会被用户程序意外访问或…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
