news 2026/2/7 21:38:57

C++ 深度解析:从基础到高级的全面指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++ 深度解析:从基础到高级的全面指南

C++ 深度解析:从基础到高级的全面指南

一、C++ 语言概述与历史演进

1.1 C++ 的起源与发展

C++ 由 Bjarne Stroustrup 于 1979 年在贝尔实验室创建,最初称为 "C with Classes"。

发展历程

  • 1983年:正式命名为 C++

  • 1985年:第一个商业版本发布

  • 1998年:C++98 成为首个国际标准(ISO/IEC 14882:1998)

  • 2003年:C++03 标准发布

  • 2011年:C++11(重大更新,现代 C++ 的起点)

  • 2014年:C++14

  • 2017年:C++17

  • 2020年:C++20(又一次重大更新)

  • 2023年:C++23(最新标准)

1.2 C++ 的设计哲学

  • 零开销原则:不使用的特性不应带来额外开销

  • 直接映射硬件:支持低级内存操作

  • 多范式编程:支持过程化、面向对象、泛型、函数式编程

  • 向后兼容性:保持与 C 的高度兼容

二、C++ 核心语法深度解析

2.1 内存管理与指针

cpp

// 指针深度示例 void advanced_pointer_demo() { // 1. 多级指针 int value = 42; int* ptr = &value; int** ptr_to_ptr = &ptr; int*** ptr_to_ptr_to_ptr = &ptr_to_ptr; // 2. 指针算术 int arr[5] = {1, 2, 3, 4, 5}; int* arr_ptr = arr; // 指针加减法 int* third_element = arr_ptr + 2; // 指向 arr[2] ptrdiff_t diff = third_element - arr_ptr; // 结果为 2 // 3. 函数指针 using FuncPtr = int(*)(int, int); FuncPtr add = [](int a, int b) { return a + b; }; FuncPtr multiply = [](int a, int b) { return a * b; }; // 4. 成员函数指针 class Calculator { public: int add(int a, int b) { return a + b; } int multiply(int a, int b) { return a * b; } }; using MemberFuncPtr = int(Calculator::*)(int, int); MemberFuncPtr mem_func = &Calculator::add; Calculator calc; int result = (calc.*mem_func)(3, 4); // 结果为 7 }

2.2 引用与移动语义

cpp

// 引用与移动语义深度示例 class Resource { int* data; size_t size; public: // 构造函数 Resource(size_t sz) : size(sz) { data = new int[sz]; std::cout << "Resource allocated\n"; } // 析构函数 ~Resource() { delete[] data; std::cout << "Resource freed\n"; } // 拷贝构造函数(深拷贝) Resource(const Resource& other) : size(other.size) { data = new int[size]; std::copy(other.data, other.data + size, data); std::cout << "Resource copied\n"; } // 移动构造函数 Resource(Resource&& other) noexcept : data(other.data), size(other.size) { other.data = nullptr; other.size = 0; std::cout << "Resource moved\n"; } // 拷贝赋值运算符 Resource& operator=(const Resource& other) { if (this != &other) { delete[] data; size = other.size; data = new int[size]; std::copy(other.data, other.data + size, data); std::cout << "Resource copy assigned\n"; } return *this; } // 移动赋值运算符 Resource& operator=(Resource&& other) noexcept { if (this != &other) { delete[] data; data = other.data; size = other.size; other.data = nullptr; other.size = 0; std::cout << "Resource move assigned\n"; } return *this; } // 完美转发示例 template<typename... Args> static Resource create(Args&&... args) { return Resource(std::forward<Args>(args)...); } };

三、面向对象编程高级特性

3.1 多重继承与虚继承

cpp

// 多重继承与虚继承深度示例 class Interface1 { public: virtual void method1() = 0; virtual ~Interface1() = default; }; class Interface2 { public: virtual void method2() = 0; virtual ~Interface2() = default; }; // 虚基类解决菱形继承问题 class Base { protected: int base_data; public: Base(int val) : base_data(val) {} virtual ~Base() = default; }; class Derived1 : virtual public Base { public: Derived1(int val) : Base(val) {} }; class Derived2 : virtual public Base { public: Derived2(int val) : Base(val) {} }; // 多重继承类 class FinalClass : public Derived1, public Derived2, public Interface1, public Interface2 { int final_data; public: // 虚继承时,最终派生类负责初始化虚基类 FinalClass(int base_val, int final_val) : Base(base_val), Derived1(base_val), Derived2(base_val), final_data(final_val) {} void method1() override { std::cout << "Method1 implemented\n"; } void method2() override { std::cout << "Method2 implemented\n"; } // 协变返回类型示例 virtual FinalClass* clone() const { return new FinalClass(*this); } };

3.2 类型转换运算符

cpp

class SmartString { std::string data; public: SmartString(const std::string& str) : data(str) {} // 转换运算符 operator std::string() const { return data; } operator const char*() const { return data.c_str(); } // bool 转换运算符(用于条件判断) explicit operator bool() const { return !data.empty(); } // 函数调用运算符 char operator()(size_t index) const { if (index < data.size()) { return data[index]; } throw std::out_of_range("Index out of range"); } };

四、模板与泛型编程

4.1 模板元编程

cpp

// 编译时计算:阶乘模板 template<unsigned n> struct Factorial { static const unsigned long long value = n * Factorial<n - 1>::value; }; template<> struct Factorial<0> { static const unsigned long long value = 1; }; // 类型特征(Type Traits) template<typename T> struct TypeInfo { static const char* name() { return "unknown"; } }; template<> struct TypeInfo<int> { static const char* name() { return "int"; } }; template<> struct TypeInfo<double> { static const char* name() { return "double"; } }; // 可变参数模板 template<typename... Args> class Tuple; template<typename Head, typename... Tail> class Tuple<Head, Tail...> { Head head; Tuple<Tail...> tail; public: Tuple(const Head& h, const Tail&... t) : head(h), tail(t...) {} template<size_t Index> auto get() const -> typename std::conditional< Index == 0, Head, decltype(tail.template get<Index - 1>()) >::type { if constexpr (Index == 0) { return head; } else { return tail.template get<Index - 1>(); } } }; template<> class Tuple<> {};

4.2 概念(C++20)

cpp

// C++20 概念示例 template<typename T> concept Arithmetic = std::is_arithmetic_v<T>; template<typename T> concept Addable = requires(T a, T b) { { a + b } -> std::convertible_to<T>; }; template<typename T> concept Container = requires(T t) { typename T::value_type; typename T::iterator; typename T::const_iterator; { t.begin() } -> std::same_as<typename T::iterator>; { t.end() } -> std::same_as<typename T::iterator>; { t.size() } -> std::integral; }; // 使用概念的模板函数 template<Arithmetic T> T add(T a, T b) { return a + b; } template<Container C> void process_container(const C& container) { std::cout << "Container with " << container.size() << " elements\n"; } // 约束的 auto 参数 void print_addable(const Addable auto& a, const Addable auto& b) { std::cout << a + b << '\n'; }

五、现代 C++ 特性深度解析

5.1 智能指针与所有权语义

cpp

class Object { public: Object() { std::cout << "Object created\n"; } ~Object() { std::cout << "Object destroyed\n"; } void method() { std::cout << "Method called\n"; } }; void smart_pointer_demo() { // 1. unique_ptr:独占所有权 std::unique_ptr<Object> up1 = std::make_unique<Object>(); std::unique_ptr<Object> up2 = std::move(up1); // 所有权转移 // 2. shared_ptr:共享所有权 std::shared_ptr<Object> sp1 = std::make_shared<Object>(); { std::shared_ptr<Object> sp2 = sp1; // 引用计数增加 std::cout << "Use count: " << sp2.use_count() << "\n"; } // sp2 析构,引用计数减少 // 3. weak_ptr:弱引用,不增加引用计数 std::weak_ptr<Object> wp = sp1; if (auto locked = wp.lock()) { // 尝试提升为 shared_ptr locked->method(); } // 4. 自定义删除器 std::unique_ptr<Object, void(*)(Object*)> custom_deleter(new Object(), [](Object* p) { std::cout << "Custom delete\n"; delete p; }); // 5. 数组支持 std::unique_ptr<Object[]> array_ptr = std::make_unique<Object[]>(5); }

5.2 并发与多线程

cpp

#include <atomic> #include <thread> #include <future> #include <mutex> #include <condition_variable> #include <semaphore> #include <latch> #include <barrier> class ThreadSafeQueue { private: mutable std::mutex mutex_; std::queue<int> queue_; std::condition_variable cond_; public: void push(int value) { std::lock_guard<std::mutex> lock(mutex_); queue_.push(value); cond_.notify_one(); // 通知等待的线程 } int pop() { std::unique_lock<std::mutex> lock(mutex_); // 等待条件:队列不为空 cond_.wait(lock, [this] { return !queue_.empty(); }); int value = queue_.front(); queue_.pop(); return value; } bool try_pop(int& value) { std::lock_guard<std::mutex> lock(mutex_); if (queue_.empty()) { return false; } value = queue_.front(); queue_.pop(); return true; } }; // 原子操作示例 class AtomicCounter { std::atomic<int> counter{0}; std::atomic_flag spinlock = ATOMIC_FLAG_INIT; public: void increment() { counter.fetch_add(1, std::memory_order_relaxed); } int get() const { return counter.load(std::memory_order_acquire); } // 自旋锁实现 void lock() { while (spinlock.test_and_set(std::memory_order_acquire)) { std::this_thread::yield(); // 让出 CPU } } void unlock() { spinlock.clear(std::memory_order_release); } }; // async/future 示例 void async_computation() { // 启动异步任务 std::future<int> future_result = std::async(std::launch::async, []() { std::this_thread::sleep_for(std::chrono::seconds(2)); return 42; }); // 等待结果(可以在这期间做其他工作) std::cout << "Waiting for result...\n"; // 获取结果(如果未完成,会阻塞) int result = future_result.get(); std::cout << "Result: " << result << "\n"; // promise/future 通信 std::promise<int> promise; std::future<int> future = promise.get_future(); std::thread worker([&promise]() { std::this_thread::sleep_for(std::chrono::seconds(1)); promise.set_value(100); }); std::cout << "Promise result: " << future.get() << "\n"; worker.join(); }

六、C++ 性能优化技术

6.1 内存对齐与缓存优化

cpp

// 内存对齐示例 struct alignas(64) CacheAlignedStruct { int data1; int data2; // 确保整个结构体大小为 64 字节(常见缓存行大小) char padding[64 - 2 * sizeof(int)]; }; // 避免伪共享(false sharing) class PaddedCounter { alignas(64) std::atomic<int> counter1; // 单独缓存行 char padding1[64]; alignas(64) std::atomic<int> counter2; // 单独缓存行 char padding2[64]; public: void increment1() { counter1.fetch_add(1, std::memory_order_relaxed); } void increment2() { counter2.fetch_add(1, std::memory_order_relaxed); } }; // 数据布局优化 struct OptimizedDataLayout { // 热数据(频繁访问) int frequently_used_field1; int frequently_used_field2; // 冷数据(不常访问) std::string rarely_used_field; std::vector<int> large_data; // 方法分离热/冷路径 void hot_path_operation() { // 只操作热数据 frequently_used_field1++; frequently_used_field2 *= 2; } void cold_path_operation() { // 操作冷数据 rarely_used_field = "processed"; } };

6.2 编译器优化与内联汇编

cpp

// 编译器指令示例 [[nodiscard]] int compute_value() { return 42; } [[maybe_unused]] void unused_function() { // 可能不会被使用的函数 } // 内联汇编示例(x86-64) void inline_assembly_demo() { int a = 10, b = 20, result; asm volatile ( "addl %%ebx, %%eax;" // eax = eax + ebx : "=a"(result) // 输出操作数 : "a"(a), "b"(b) // 输入操作数 : // 破坏的寄存器列表 ); // 内存屏障 asm volatile("mfence" ::: "memory"); // 时间戳计数器 unsigned long long tsc; asm volatile("rdtsc" : "=A"(tsc)); std::cout << "Result: " << result << ", TSC: " << tsc << "\n"; } // 编译器内置函数 void builtin_functions() { // 分支预测提示 if (__builtin_expect(condition(), 1)) { // 很可能执行的分支 } // 位操作 int x = 42; int count = __builtin_popcount(x); // 统计 1 的位数 // 类型转换 float f = 3.14f; int i = __builtin_bit_cast(int, f); // C++20 // 栈保护 void* canary = __builtin_return_address(0); }

七、C++ 设计模式实现

7.1 RAII(资源获取即初始化)

cpp

template<typename T> class ScopedLock { T& mutex_; bool locked_; public: explicit ScopedLock(T& mutex) : mutex_(mutex), locked_(true) { mutex_.lock(); } ~ScopedLock() { if (locked_) { mutex_.unlock(); } } // 禁止拷贝 ScopedLock(const ScopedLock&) = delete; ScopedLock& operator=(const ScopedLock&) = delete; // 允许移动 ScopedLock(ScopedLock&& other) noexcept : mutex_(other.mutex_), locked_(other.locked_) { other.locked_ = false; } void unlock() { if (locked_) { mutex_.unlock(); locked_ = false; } } void lock() { if (!locked_) { mutex_.lock(); locked_ = true; } } };

7.2 策略模式与类型擦除

cpp

// 基于模板的策略模式 template<typename DrawStrategy> class Shape { DrawStrategy drawer; public: template<typename... Args> void draw(Args&&... args) { drawer.draw(std::forward<Args>(args)...); } }; // 运行时策略(类型擦除) class Drawable { struct Concept { virtual ~Concept() = default; virtual void draw() const = 0; virtual std::unique_ptr<Concept> clone() const = 0; }; template<typename T> struct Model : Concept { T data; Model(T value) : data(std::move(value)) {} void draw() const override { data.draw(); } std::unique_ptr<Concept> clone() const override { return std::make_unique<Model>(data); } }; std::unique_ptr<Concept> pimpl; public: template<typename T> Drawable(T value) : pimpl(std::make_unique<Model<T>>(std::move(value))) {} Drawable(const Drawable& other) : pimpl(other.pimpl->clone()) {} Drawable(Drawable&&) noexcept = default; Drawable& operator=(const Drawable& other) { pimpl = other.pimpl->clone(); return *this; } void draw() const { pimpl->draw(); } };

八、C++ 标准库深度探索

8.1 迭代器与范围

cpp

// 自定义迭代器 template<typename T> class VectorIterator { T* ptr; public: using iterator_category = std::random_access_iterator_tag; using value_type = T; using difference_type = std::ptrdiff_t; using pointer = T*; using reference = T&; VectorIterator(T* p = nullptr) : ptr(p) {} // 解引用 reference operator*() const { return *ptr; } pointer operator->() const { return ptr; } // 递增递减 VectorIterator& operator++() { ++ptr; return *this; } VectorIterator operator++(int) { auto tmp = *this; ++ptr; return tmp; } // 算术运算 VectorIterator operator+(difference_type n) const { return VectorIterator(ptr + n); } difference_type operator-(const VectorIterator& other) const { return ptr - other.ptr; } // 比较 bool operator==(const VectorIterator& other) const { return ptr == other.ptr; } bool operator!=(const VectorIterator& other) const { return ptr != other.ptr; } }; // C++20 范围示例 void ranges_example() { std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // 管道操作符 auto result = numbers | std::views::filter([](int n) { return n % 2 == 0; }) | std::views::transform([](int n) { return n * n; }) | std::views::take(3); for (int n : result) { std::cout << n << " "; } // 生成无限序列 auto infinite = std::views::iota(1) | std::views::transform([](int n) { return n * 2; }); // 惰性求值:不会实际生成无限元素 for (int n : infinite | std::views::take(5)) { std::cout << n << " "; } }

8.2 算法与函数式编程

cpp

void algorithms_demo() { std::vector<int> data = {5, 3, 8, 1, 9, 2, 6, 7, 4}; // 并行算法(C++17) std::sort(std::execution::par, data.begin(), data.end()); // 变换-规约模式 auto sum_of_squares = std::transform_reduce( std::execution::par, data.begin(), data.end(), 0.0, std::plus<>(), [](int x) { return x * x; } ); // 内积计算 std::vector<int> a = {1, 2, 3}; std::vector<int> b = {4, 5, 6}; int dot_product = std::inner_product( a.begin(), a.end(), b.begin(), 0 ); // 扫描操作(前缀和) std::vector<int> prefix_sum(data.size()); std::inclusive_scan( std::execution::par, data.begin(), data.end(), prefix_sum.begin() ); // 采样算法 std::vector<int> sample(3); std::sample( data.begin(), data.end(), sample.begin(), 3, std::mt19937{std::random_device{}()} ); // 擦除-移除惯用法(C++20) std::erase_if(data, [](int x) { return x % 2 == 0; }); }

九、C++ 工程实践

9.1 构建系统与模块化

cpp

// CMakeLists.txt 示例 /* cmake_minimum_required(VERSION 3.20) project(MyProject VERSION 1.0.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 模块化配置 add_library(core INTERFACE) target_include_directories(core INTERFACE include) target_compile_features(core INTERFACE cxx_std_20) add_library(math STATIC src/math.cpp) target_link_libraries(math PUBLIC core) add_executable(main src/main.cpp) target_link_libraries(main PRIVATE math core) # 条件编译 option(ENABLE_DEBUG "Enable debug features" OFF) if(ENABLE_DEBUG) target_compile_definitions(main PRIVATE DEBUG_MODE=1) endif() # 依赖管理 find_package(Boost 1.70 REQUIRED COMPONENTS filesystem system) target_link_libraries(main PRIVATE Boost::filesystem Boost::system) */ // 模块示例(C++20) export module math; export namespace math { export double sqrt(double x); export double pow(double base, double exp); export template<typename T> concept Arithmetic = std::is_arithmetic_v<T>; export template<Arithmetic T> T add(T a, T b) { return a + b; } }

9.2 测试与调试

cpp

// Google Test 风格测试示例 #define TEST_CASE(name) \ class Test##name : public ::testing::Test { \ protected: \ void SetUp() override {} \ void TearDown() override {} \ }; \ TEST_F(Test##name, name) class Calculator { public: int add(int a, int b) { return a + b; } int multiply(int a, int b) { return a * b; } }; TEST_CASE(CalculatorTests) { Calculator calc; // 断言 ASSERT_EQ(calc.add(2, 3), 5); ASSERT_NE(calc.multiply(3, 4), 11); ASSERT_TRUE(calc.add(0, 0) == 0); // 浮点数比较 ASSERT_NEAR(1.0/3.0, 0.33333, 0.00001); // 异常断言 ASSERT_THROW(throw std::runtime_error("error"), std::runtime_error); ASSERT_NO_THROW(calc.add(1, 1)); // 性能测试 auto start = std::chrono::high_resolution_clock::now(); for (int i = 0; i < 1000000; ++i) { calc.add(i, i + 1); } auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start); ASSERT_LT(duration.count(), 100); // 应在 100ms 内完成 } // 调试宏 #ifdef DEBUG_MODE #define DEBUG_LOG(msg) \ std::cout << __FILE__ << ":" << __LINE__ << " " << msg << std::endl #define DEBUG_ASSERT(condition, msg) \ if (!(condition)) { \ std::cerr << "Assertion failed: " << #condition \ << " " << msg << std::endl; \ std::abort(); \ } #else #define DEBUG_LOG(msg) #define DEBUG_ASSERT(condition, msg) #endif

十、C++ 高级主题

10.1 协程(C++20)

cpp

#include <coroutine> #include <iostream> #include <stdexcept> // 生成器协程 template<typename T> class [[nodiscard]] Generator { public: struct promise_type { T value_; std::exception_ptr exception_; Generator get_return_object() { return Generator(std::coroutine_handle<promise_type>::from_promise(*this)); } std::suspend_always initial_suspend() { return {}; } std::suspend_always final_suspend() noexcept { return {}; } void unhandled_exception() { exception_ = std::current_exception(); } void return_void() {} std::suspend_always yield_value(T value) { value_ = std::move(value); return {}; } }; std::coroutine_handle<promise_type> coro_; explicit Generator(std::coroutine_handle<promise_type> h) : coro_(h) {} ~Generator() { if (coro_) coro_.destroy(); } // 禁止拷贝 Generator(const Generator&) = delete; Generator& operator=(const Generator&) = delete; // 允许移动 Generator(Generator&& other) noexcept : coro_(other.coro_) { other.coro_ = {}; } bool next() { if (!coro_) return false; coro_.resume(); return !coro_.done(); } T value() const { if (!coro_) throw std::runtime_error("Empty generator"); if (coro_.promise().exception_) { std::rethrow_exception(coro_.promise().exception_); } return coro_.promise().value_; } }; Generator<int> fibonacci(int limit) { int a = 0, b = 1; while (a <= limit) { co_yield a; int next = a + b; a = b; b = next; } } void coroutine_demo() { auto gen = fibonacci(100); while (gen.next()) { std::cout << gen.value() << " "; } std::cout << "\n"; }

10.2 反射与元数据(未来特性)

cpp

// 编译时反射示例(提案中) /* struct Person { std::string name; int age; double salary; // 使用属性(可能成为 C++26 或以后的标准) [[meta::property]] std::string name_property = "name"; [[meta::property]] std::string age_property = "age"; [[meta::property]] std::string salary_property = "salary"; }; template<typename T> void print_fields() { // 编译时遍历字段 for... (auto field : T::fields) { std::cout << field.name << ": " << field.type.name() << "\n"; } } void reflection_demo() { Person p{"John", 30, 50000.0}; // 运行时反射(可能需要库支持) auto refl = reflect(p); for (auto& member : refl.members()) { std::cout << member.name() << " = " << member.get(p).to_string() << "\n"; } // 序列化/反序列化 auto json = serialize<json_format>(p); Person p2 = deserialize<json_format>(json); } */

总结

C++ 是一门极其强大且复杂的语言,它提供了:

  1. 多层抽象能力:从底层硬件操作到高级抽象

  2. 零开销抽象:高级特性不带来运行时开销

  3. 多范式支持:面向对象、泛型、函数式、过程式

  4. 强大的标准库:涵盖算法、容器、并发、文件系统等

  5. 现代语言特性:模块、协程、概念等持续演进

学习建议:

  1. 从基础语法和内存管理开始

  2. 深入理解面向对象和模板编程

  3. 掌握现代 C++(C++11 及以后)特性

  4. 学习设计模式和最佳实践

  5. 实践系统级编程和性能优化

未来发展方向:

  • C++26 正在制定中,将带来更多现代特性

  • 生态工具持续改进(构建系统、包管理、IDE 支持)

  • 在系统编程、游戏开发、高频交易等领域持续主导地位

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/6 10:13:32

如何衡量推广效果(如投产比、转化率)?一位餐饮老板的实战自白

凌晨两点&#xff0c;我蹲在螺蛳粉店的台阶上&#xff0c;盯着手机里豆包APP的搜索结果页面。这是今天第三次确认——我的店名终于出现在“附近好吃的螺蛳粉”搜索结果的第一位。三个月前&#xff0c;我根本不敢想这样的场景。被算法“卡脖子”的生意 我的店开在上海&#xff0…

作者头像 李华
网站建设 2026/2/7 22:50:03

大模型安全威胁全解析,Agent架构设计避坑指南,小白必看

一、报告价值锚点 趋势与机遇 Agent-first设计&#xff1a;业务流程原生嵌入Agent基因&#xff0c;组织向“人机混编”转型。虚拟劳动力平台&#xff1a;中小企借标准化Agent租赁切入智能化&#xff0c;B2B服务蓝海开启。生态级互联互通&#xff1a;Agent App Store雏形浮现&…

作者头像 李华
网站建设 2026/2/7 8:33:19

SMDJ45A单向 TVS瞬态抑制二极管 :3000W浪涌保护管 防雷击抗静电

SMDJ45A单向 TVS瞬态抑制二极管 二极管产品已经跟我们的生活有着密不可分的联系了&#xff0c; TVS瞬态抑制二极管&#xff0c;是一种高效能保护二极管&#xff0c;产品体积小、功率大、响应快等诸多优点 TVS瞬态抑制二极管SMDJ45A&#xff0c;是一种二极管形式的高效能被动保…

作者头像 李华
网站建设 2026/2/6 19:02:22

Foundation 文本

Foundation 5 文本&#xff08;Typography&#xff09; Foundation 5 提供了丰富的排版&#xff08;Typography&#xff09;工具&#xff0c;包括标题、段落、内联文本元素、对齐方式等。默认样式基于 Sass 变量&#xff0c;可自定义&#xff0c;但开箱即用非常美观。 1. 基本…

作者头像 李华
网站建设 2026/2/6 16:10:05

Sui 主网升级至 V1.61.2

其他升级要点如下所示&#xff1a; 协议 #24343&#xff1a;对 coin.move 的框架进行了修改。 gRPC #24244&#xff1a;对于尚未完全写入的新检查点&#xff0c;不再返回 “Internal Error”&#xff0c;而是返回 “Not Found”。 GraphQL #24202&#xff1a;修复了一个与…

作者头像 李华