掌握C++20 import的黄金法则,提前锁定下一代C++开发先机

第一章:掌握C++20 import的黄金法则,提前锁定下一代C++开发先机

C++20 引入了模块(Modules),标志着头文件包含机制的重大演进。`import` 关键字取代传统的 `#include`,从根本上解决了宏污染、重复解析和编译效率低下的顽疾。开发者现在可以将接口封装为独立模块,实现真正的隔离与复用。

模块声明与导入的基本语法

模块以 `module` 关键字声明,可通过 `export` 控制对外暴露的接口。使用 `import` 导入已定义的模块,避免预处理器展开带来的开销。
// math.ixx - 模块接口文件
export module math;
export int add(int a, int b) {
    return a + b;
}

// main.cpp - 主程序文件
import math;
#include <iostream>

int main() {
    std::cout << add(3, 4) << '\n'; // 输出 7
    return 0;
}
上述代码中,`math.ixx` 是模块接口单元,`main.cpp` 通过 `import math;` 直接引入功能,无需头文件。

模块带来的核心优势

  • 编译速度显著提升,不再重复处理头文件内容
  • 命名空间与宏作用域更清晰,减少意外冲突
  • 支持私有模块片段,隐藏实现细节
  • 允许分段模块组织,便于大型项目维护

主流编译器支持现状

编译器支持状态启用指令
MSVC (Visual Studio 2019+)完整支持/std:c++20 /experimental:module
Clang 16+部分支持-fmodules -std=c++20
GCC 13+实验性支持-fmodules-ts -std=c++20
采用模块化设计不仅是语法更新,更是工程思维的跃迁。尽早掌握 `import` 的使用模式,将在未来 C++ 项目中占据架构主动权。

第二章:深入理解C++20模块与import机制

2.1 模块的基本概念与传统头文件的对比

在现代C++开发中,模块(Module)作为一种新的组织代码的方式,逐步取代传统的头文件机制。相比头文件通过文本包含实现声明共享,模块以语义方式导出接口,避免重复解析和宏污染。
模块的核心优势
  • 编译速度提升:无需重复处理头文件内容
  • 命名空间更清晰:显式控制导出符号
  • 依赖管理更精确:按需编译,减少冗余
代码示例:模块定义
export module MathUtils;

export int add(int a, int b) {
    return a + b;
}
上述代码定义了一个名为 MathUtils 的模块,并导出函数 add。编译器将生成模块接口文件,供其他单元直接导入使用,不再需要 #include 预处理指令。
与头文件的对比
特性模块头文件
编译效率高低
符号隔离强弱

2.2 import声明的语法结构与语义解析

在Go语言中,`import`声明用于引入外部包以使用其导出的函数、类型和变量。基本语法如下:
import "fmt"
import "os"
上述写法可合并为更简洁的形式:
import (
    "fmt"
    "os"
)
该格式称为分组导入,推荐用于多个包的引入。每个导入路径对应一个标准库或模块中的包。
导入别名与副作用导入
支持为导入包指定别名,解决命名冲突:
import myfmt "fmt"
此时可使用`myfmt.Println`调用原`fmt`包功能。 若仅执行包初始化逻辑而不直接引用其成员,可使用点导入或空白标识符:
  • import _ "database/sql":触发驱动注册等副作用
  • import . "fmt":将符号引入当前作用域(慎用)

2.3 模块接口单元与实现单元的组织方式

在大型软件系统中,模块的接口单元与实现单元应分离设计,以提升可维护性与测试便利性。接口定义行为契约,实现则专注具体逻辑。
接口与实现的目录结构
典型的组织方式是按功能划分目录,每个模块包含独立的 `interface` 与 `implementation` 子包:

module/
├── user/
│   ├── interface.go    // 定义 UserService 接口
│   └── service.go      // 实现 UserService 接口
该结构清晰隔离抽象与细节,便于依赖注入和单元测试。
接口定义示例

type UserService interface {
    GetUser(id int) (*User, error)
    CreateUser(u *User) error
}
此接口声明了用户服务的核心方法,不涉及数据库、HTTP 等具体实现细节。
优势分析
  • 支持多实现切换,如 mock 实现用于测试
  • 降低模块间耦合,促进面向接口编程
  • 便于静态检查和工具生成代码

2.4 模块分区与私有片段的使用场景

在大型应用架构中,模块分区是实现职责分离的关键手段。通过将功能划分为独立模块,可提升代码可维护性与团队协作效率。
私有片段的封装优势
私有片段用于隐藏内部实现细节,仅暴露必要接口。这种方式增强了模块的安全性与稳定性。
// 定义私有片段
func (m *Module) internalProcess() error {
    // 仅限模块内部调用
    return nil
}
上述代码中,internalProcess 方法未导出,确保外部包无法直接访问,实现访问控制。
典型应用场景
  • 多租户系统中的数据隔离
  • 微服务间接口边界控制
  • SDK 内部逻辑封装

2.5 编译器对import的支持现状与配置方法

现代编译器普遍支持模块化导入机制,但具体实现因语言和工具链而异。以 Go 语言为例,其原生支持通过 `import` 关键字引入标准库或第三方包。
基本导入语法示例
import (
    "fmt"
    "github.com/user/project/utils"
)
该代码块展示了如何同时导入标准库(fmt)和远程模块(utils)。编译器在构建时会解析这些依赖,并从本地缓存或远程仓库获取对应模块版本。
模块路径解析与配置
Go 使用 go.mod 文件管理依赖版本。典型配置如下:
指令作用
module example/app声明模块根路径
require github.com/user/utils v1.2.0指定依赖及其版本
编译器依据此文件锁定依赖树,确保构建一致性。启用模块功能需设置环境变量 GO111MODULE=on,并在项目根目录执行 go mod init 初始化。

第三章:从零开始构建模块化C++项目

3.1 创建第一个模块接口并正确导出符号

在Go模块开发中,定义清晰的接口是构建可维护系统的第一步。通过`exported`命名约定(首字母大写),可控制符号的可见性。
接口定义与导出规范
package calculator

// Add 为公开函数,可被外部包调用
func Add(a, b int) int {
    return doAdd(a, b)
}

// doAdd 为私有函数,仅限包内使用
func doAdd(x, y int) int {
    return x + y
}
上述代码中,Add 函数首字母大写,对外导出;而 doAdd 为私有实现,封装内部逻辑。
导出符号的依赖关系
  • 导出函数应尽量减少暴露内部结构
  • 建议通过接口隔离实现,提升测试性
  • 避免导出未使用的变量或类型

3.2 在主程序中导入模块并验证功能完整性

在完成模块开发后,需将其集成至主程序并验证其行为是否符合预期。首先通过标准导入机制引入模块,确保路径配置正确。
模块导入与初始化
使用 Python 的 import 语句加载自定义模块,结构清晰且易于维护:
from utils.data_processor import DataProcessor
from utils.validator import validate_input

# 初始化处理器
processor = DataProcessor()
上述代码从 utils 包导入核心类与函数。其中 DataProcessor 负责数据转换,validate_input 提供输入校验逻辑。
功能验证流程
通过构造测试用例验证模块输出一致性:
  • 准备标准化输入数据样本
  • 调用处理接口并捕获返回值
  • 比对实际输出与预期结果
  • 记录异常并定位依赖问题
该流程确保模块在主程序上下文中稳定运行,具备良好的可测试性与可维护性。

3.3 跨模块依赖管理与编译顺序控制

在大型项目中,模块间的依赖关系复杂,合理的依赖管理是确保正确编译的关键。构建系统需识别模块间依赖并据此确定编译顺序。
依赖声明示例

// go.mod
module project/service

require (
    project/core v1.2.0
    project/utils v0.8.0
)
该配置明确声明了当前模块对 core 和 utils 的版本依赖,Go 模块系统据此解析依赖图谱。
编译顺序决策机制
构建工具依据依赖拓扑排序决定编译序列:
  • 无依赖模块优先编译
  • 被依赖模块先于依赖者编译
  • 循环依赖将导致编译失败
模块依赖项编译阶段
utils无1
coreutils2
servicecore, utils3

第四章:优化与进阶实践技巧

4.1 避免模块循环依赖的设计模式

在大型软件系统中,模块间的循环依赖会破坏可维护性与可测试性。通过合理的设计模式,可有效切断此类耦合。
依赖注入(Dependency Injection)
将依赖关系从内部创建转为外部传入,打破硬编码依赖:

type ServiceA struct {
    B *ServiceB
}

type ServiceB struct {
    A *ServiceA
}
// 改为通过构造函数注入,而非直接实例化
func NewServiceA(b *ServiceB) *ServiceA {
    return &ServiceA{B: b}
}
该方式使依赖方向单一化,便于单元测试和替换实现。
接口隔离与中间层解耦
  • 定义抽象接口,模块依赖于抽象而非具体实现
  • 引入事件总线或消息队列作为通信中介,实现异步解耦
通过分层架构与控制反转原则,系统模块间可保持松散耦合,显著降低循环依赖风险。

4.2 提升编译速度:预编译模块的优势利用

现代构建系统中,预编译模块(Precompiled Modules)通过将频繁使用的头文件或接口预先编译为二进制格式,显著减少重复解析开销。
工作原理
预编译模块将稳定接口编译为模块单元(如 `.pcm` 文件),后续编译直接引用该单元,避免重复词法与语法分析。
配置示例
以 Clang 为例,启用 C++20 模块编译:
clang++ -std=c++20 -fmodules -c string_utils.cppm -o string_utils.pcm
clang++ -std=c++20 -fmodule-file=string_utils.pcm main.cpp -o app
第一行生成模块文件 `string_utils.pcm`,第二行链接模块进行最终编译。参数 `-fmodules` 启用模块支持,`-fmodule-file` 指定已编译模块路径,避免重复处理。
性能对比
方式首次编译(s)增量编译(s)
传统头文件12.48.7
预编译模块10.12.3
可见在增量构建中,预编译模块节省约73%时间,长期收益显著。

4.3 混合使用传统头文件与现代模块的过渡策略

在向现代C++模块迁移过程中,渐进式整合是关键。项目可先将稳定组件封装为模块,同时保留原有头文件接口供旧代码调用。
双接口共存模式
通过模块分区和兼容头文件实现平滑过渡:
// math_lib.ixx
export module math_lib;
export int add(int a, int b) { return a + b; }

// 兼容头文件 math_lib.h
#include <cpp20/module>
import math_lib;
上述设计允许新代码直接导入模块,旧代码仍包含头文件,编译器自动路由至同一实现。
构建系统配置建议
  • 为模块文件启用/std:c++20 /experimental:module编译选项
  • 生成IFC缓存以加速跨模块依赖解析
  • 使用PCH混合编译策略降低重构成本

4.4 构建系统(CMake)对模块的集成支持

CMake 提供了强大的模块化构建支持,通过 `add_subdirectory()` 可将独立模块无缝集成到主项目中。
模块化结构组织
推荐将功能模块放在独立目录中,并在根 CMakeLists.txt 中引入:

# 根目录 CMakeLists.txt
add_subdirectory(math_lib)
add_subdirectory(ui_module)
该指令使 CMake 递归处理子目录中的 CMakeLists.txt,实现逻辑解耦与编译隔离。
依赖管理与导出
模块可使用 `target_link_libraries()` 声明依赖关系:

# math_lib/CMakeLists.txt
add_library(math_lib STATIC calc.cpp)
target_include_directories(math_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
`PUBLIC` 表示头文件路径对链接此库的目标可见,便于上层模块包含使用。
  • 模块间通过目标名称引用,避免硬编码路径
  • 支持条件编译,如 option(ENABLE_UI "Build UI module" ON)

第五章:展望C++23及未来模块系统的演进方向

模块化编程的深度集成
C++23正式引入了模块(Modules)作为语言一级特性,取代传统头文件包含机制。开发者可使用import直接引入命名模块,显著提升编译速度与封装性。

// 定义一个数学模块
export module math_utils;
export int add(int a, int b) {
    return a + b;
}
构建系统适配策略
主流构建工具如CMake已支持模块单元编译。需在CMakeLists.txt中启用实验性模块标志,并指定模块映射文件生成方式:
  • 设置编译器标志:-fmodules-ts(Clang)或 /experimental:module(MSVC)
  • 使用.cxxmip或.ifc文件缓存模块接口
  • 通过add_library(... MODULE)声明模块目标
跨平台模块分发实践
平台支持编译器模块缓存路径
LinuxClang 16+/usr/local/lib/modules
WindowsMSVC 19.30+%ProgramFiles%\MyModule\ifc
模块与模板的协同优化
模块允许将复杂模板实现封装为导出接口,避免隐式实例化污染。例如,将元编程工具包组织为独立模块,提升大型项目链接效率。
流程图:源文件 → 模块接口单元(.ixx) → 编译为IFC二进制 → 目标代码生成 → 链接可执行文件
未来标准计划引入模块版本控制与远程导入机制,可能支持类似import std@2.0;的语义化版本引用模式,进一步推动C++生态的现代化重构。
C++(20):模块export和import的限制 9.import仅能用于全局作用域中,也就是不能像#include那样用于函数、类、命名空间的内部。7.被导出的符号,第一次导出声明时需要使用export,后续的声明或定义不能使用export。的方式导出整个命名空间。4.export关键字只能使用于全局命名空间或具名命名空间中,不能用于类或函数的内部。注1:必须首先通过export导出符号,然后才能通过using的方式暴露符号。5.命名空间中被导出的符号,可以通过using将符号直接暴露出来。6.直接导出命名空间中的符号,但不能是静态变量或静态函数。 阅读详情

相关推荐

import指令

import 创建两个标题文件来重新构造C++源代码内的类型库内容。主要标头文件类似于生产有Microsoft“接口定义语言”(MIDL)编译器生成的文件,但是是使用附加的编译器生成的代码。“主要标头文件”具有与类库相同的基名称以及.TLH扩展。次要头文件具有与类库相同的基名称,并包含有.TLH扩展。它在主要头文件中包含编译器生成的成员函数的实现并包含(#include)。

C++编程->import函数

#import指令用于从一个类型库中结合信息。该类型库的内容被转换为C++类,主要用于描述COM界面。 语法 #import "文件名" [属性] #import <文件名> [属性] 属性: 属性1,属性2,... 属性1 属性2 ... 文件名是一个包含类型库信息的文件的名称。一个文件可为如下类型之一: * ...

weixin_33883178的博客 1056

如何加载交易策略EA到MT4/MT5

1、打开MT4/MT5软件 2、首先,必须有一个EA,而且必须是mq4/ex4为扩展名。点击左上角“文件”—“打开数据文件夹”,找到安装路径 3、将EA的ex4或mq4文件放到MT4目录\MQL4\Experts里面(本文以名为Demo的EA为例) 4、如果有DLL库文件,复制到experts目录下的libraries子目录中 5、如果有tpl模板文件,复制到templates目录中 6、添加完成后重启MT4,点击允许EA运行图标 7、在导航中找到刚才安装的EA,拖拽到...

weixin_41364817的博客 7362

c++20特性(模块)

看了c++白皮书之后,发现c++20有了很大的改变,写下一些其中的内容。 模块: export指令可以使代码可以被import到另一个模块中 import指令可以使从另一个模块export出来的代码能够被使用 import的实体不会被隐式的再export出去(我的理解是A import B之后,C import A不会包含B;不对的话希望纠正我) import不会将实体代码添加到上下文中;他只会使代码能够被使用,因此未使用的import基本上是无开销的 实例: export module my_pr

qq_44751330的博客 2567

基于ADS\HFSS\Matlab的平面带通发夹滤波器设计

写在最前面,前段时间完成了一个小项目,实现13.5~14GHz的带通滤波器,算是第一个微波项目,在老师、学长、各种大神的指点下,最终完成了指标,想来这段时间收获良多,想到老师教导的,有能力的话要尽可能帮助别人,以及网络上很少面向于小白的教程,于是决定把自己做这个小项目的经过,一些关键步骤,还有软件操作和公式讲解都发出来,供大家指正借鉴。由于我目前大三,刚学习电磁场、微波工程等等,技术实在有限,同时这样是我第一次发帖子,只能尽可能的将自己确认过正确的内容,步骤以及一些经验写出来,供大家借鉴。

likaifeng12138的博客 5219

CANFD升级踩坑实录:DBC转换时DLC大于8的信号怎么处理?

本文详细探讨了CANFD升级过程中DLC大于8的信号处理问题,提供了工程化解决方案和AutoSar BSW层配置要点。通过分析CAN与CANFD的DLC本质差异,提出信号拆分重组、DLC重映射和协议层适配三种策略,并给出验证与测试方案,帮助开发者避免数据截断和通信故障。

weixin_42521843的博客 230

【转】#import 指令

C++特殊处 #import指令用于从一个类型库中结合信息。该类型库的内容被转换为C++类,主要用于描述COM界面。 语法 #import "文件名" [属性] #import <文件名> [属性] 属性: 属性1,属性2,... 属性1 属性2 ... 文件名是一个包含类型库信息的文件的名称。一个文件可为如下类型之一: * 一个类型库(.TLB或.ODL)文件。 * 一个可...

a13467778845的博客 810

STM32 FDCAN热插拔恢复机制与自动重发功能优化

本文深入分析了STM32 FDCAN在热插拔场景下触发bus-off状态导致通讯中断的根本原因,指出自动重发功能是问题关键。通过禁用自动重发、配置硬件自动恢复机制及优化总线参数,实现了FDCAN热插拔后的100%稳定恢复,为工业应用提供了可靠的CAN总线解决方案。

ice55的博客 685

【C++ 20进阶(1):模块导入 import】

模块机制有何好处呢?最大的好处便是可以大大提升编译效率,原来通过引入头文件,预编译过程中将加载此头文件包含的全部内容,include一次便加载一次,哪怕文件相同,而现在只需加载一遍export所定义的模块,将极大地提升预编译速度。本篇文章为系列文章将着重介绍C++20新特性,一是希望可以和大家交流分享,二是也便于自己巩固学习。那么如何定义自己的公共模块呢?那么如何导出自己想要导出的内容呢?

weixin_44259356的博客 2277

LAMMPS+Phonopy计算声子色散曲线

机器学习训练完势函数之后,需要对加以验证。对于晶体而言,色散曲线是其衡量计算是否准确的最重要标准,当然,还有能量,比热,RDF等性质。

qq_68842798的博客 3462

微信小程序:errno: 600001, errMsg: “uploadFile:fail errcode:-101 cronet_error_code:-10001 error_msg:net::E

微信小程序报错uploadFile:fail errcode:-101 cronet_error_code:-10001 error_msg:net::ERR_CONNECTION_RESET, custum ip is invalid, didn't find user's ip,wx.uploadFile errno: 600001 errcode:-101 ?微信小程序wx.uploadFile错误,wx.uploadFile 在真机上报下面的错误,调试工具里没有问题,其它接口在真机/调试工具都正常,

✅ 精选推荐文章 4260

C++20中常用的算法---import <algorithm>

c++20模块中常用的算法。

Brickisheavy的博客 955

论文阅读:arixv 2025 Poisoning Attacks on LLMs Require a Near-constant Number of Poison Samples

研究者做了目前最大规模的“投毒实验”,训练了从6亿参数到130亿参数的模型(覆盖了中小到大型LLM),用的训练数据量也是“最适合模型大小”的(按行业里的“Chinchilla法则”,模型越大,训练数据量也按比例增加)。总结下来就是:这篇论文告诉我们,给大语言模型投毒,比之前想的容易得多——不需要海量毒数据,只要几百条藏好后门的文档,就能让大模型“带毒工作”,而且平时还看不出来。——这比之前大家担心的“需要投毒数据占训练集一定比例”要可怕得多,因为对大模型来说,“固定数量”的毒数据更容易偷偷塞进去。

CSPhD-winston的博客 1080

vc++中的import的使用

#import 指令 1. C++中使用 COM 简单的方法是用 #import 导入 type library 2. # import 指令将 COM 产生对应的 C++类别,可以用接近於VBScript和Visual Basic的语句操作 COM 3. 使用 #import 命令就可以将该文件导入到我们的程式码中。type library 的内容将被转换为描述了 COM Interfac

有志者事竟成 6890

【踩坑记录】colmap中的相机位姿的坐标系定义及其可视化结果的隐含转换

1 坐标系定义及转换   首先介绍一下世界坐标系和相机坐标系之间的转换,它们之间是存在一个转换关系的。现假设空间中一点X,它在相机坐标系下的坐标是Xcamera,在世界坐标系下的坐标是Xworld。假设它通过R和t实现从相机坐标系到世界坐标系之间的转换: Xworld = RXcamera + t   那么,由上式,我们可以推得从世界坐标系向相机坐标系的转换关系(RT=R-1,所以通常直接使用RT即可): Xcamera = RTXworld - RTt   所以,两个坐标系之间的转换,需要看其具体

zeeq的博客 2万+

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

C++20模块( import 核心用法)

导入的是标准库模块,不是std命名空间;模块std会自动导出std::xxx所有内容,所以你能用,但仍需加前缀;std既是命名空间(组织代码),也是模块名(导入接口)——同名不同义。

ULTRAmanTAROACE的博客 1731

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

#import 指令 (C++)

已用于合并类型库中的信息。该类型库的内容转换为C++类,主要描述COM接口。   #import "filename" [attributes]   #import [attributes] 例如:   #import "c:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","ado

QLQ的专栏 5614

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

【C++20模块深度剖析】:6个必须掌握的import声明使用场景

掌握C++20模块的import声明,提升编译效率与代码组织。详解头文件替代、模块分区导入、显式接口导出等6大应用场景,解析模块单元构建与依赖管理优势。告别传统包含模式,实现更快链接与更清晰架构,值得收藏。

ByteShoal的博客 570

C/C++ 预处理程序参考——#import 指令

未完待续C/C++ 预处理程序参考#import 指令 C++ Specific #import 指令被用来把type library中的信息合并。Type library的内容被转换成 C++ classes,大部分表示成 COM 接口。 #import  "filename" [attributes]#import  [attributes] attributes 一个或多个 #im

零的技术专栏 1万+

import关键字介绍

import关键字 为什么使用? 编程时,在使用一个类如果要将多个包名.类名完全写出,会让代码变得冗长,降低了简洁度,可读性差。在源文件中显示调用import导入指定包下的类,接口 即使用Java API下的类或工程不同包下的类,都需要使用import结构 java.io.InputStream is = java.lang.System.in; java.io.InputStreamReader isr= new java.io.InputStreamReader(is); java.io.Buffer

weixin_43862596的博客 1536

vc++中的import的使用【转】

#import 指令 1. C++中使用 COM 簡單的方法是用 #import 導入 type library 2. # import 指令將 COM 產生對應的 C++類別,可以用接近於VBScript和Visual Basic的語句操作 COM 3. 使用 #import 命令就可以將該文件導入到我們的程式碼中。type library 的內容將被轉換為描述了 COM Interfac...

weixin_30321449的博客 624

你真的会用import吗?C++20模块导入机制内幕详解(仅限专家知晓)

掌握C++20模块导入导出技巧,提升编译效率与代码组织能力。深入解析import机制、模块分区、接口导出控制及命名模块的使用场景,揭示头文件替代方案与性能优势。理解模块单元与全局影响,避免常见陷阱。专家级实践指南,值得收藏。

CodePulse的博客 968

C++20模块

C++20标准中开始引入模块(module)的概念,用于解决传统的头文件包含机制在编译时间,工程代码组织等方面的问题,本文简要介绍C++20的模块机制及其使用说明或限制条件。

drivextech的博客 7725

VS2022配置C++ 20解决import std报错

注意选择ISO C++20 标准 (/std:c++20)也不能正常使用,一定选择c++ latest。(2)项目--属性--C/C++--语言--生成ISO C++23标准库模块--完成上面两个步骤,就可以正常使用import std代码了,运行成功!(1)项目--属性--常规--C++语言标准--

Color Space的博客 3232

常用C++20技术点

C++20常用技术点

u011780419的专栏 415

【现代C++】模块的使用

C++20引入了模块的概念,这是一个重要的新特性,旨在替代传统的预处理器和头文件机制。模块旨在提高编译速度、改善代码封装性、减少名称污染,并提供更好的工具支持。

karl2000的专栏 603
上一篇: C++17结构化绑定深度解析:释放数组操作的真正潜力(仅限高手)
下一篇: 【accumulate 的初始值类型深度解析】:掌握正确用法避免常见陷阱
LiteCode
博客等级 码龄1年 146粉丝 2019原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值