C++中explicit构造函数的5大使用场景(资深架构师20年实战经验总结)

第一章:explicit构造函数的核心概念与重要性

在C++中,`explicit`关键字用于修饰类的构造函数,以防止编译器执行隐式类型转换。这种机制对于避免意外的对象构造和提升代码安全性至关重要。

explicit的作用机制

当一个类的构造函数接受单个参数时,编译器会自动将其视为转换构造函数,允许隐式转换。使用`explicit`可以禁用此类隐式行为,仅允许显式调用。 例如,以下代码展示了一个未使用`explicit`可能导致的问题:

class String {
public:
    String(int size) { /* 分配指定大小的字符串缓冲区 */ }
};

void printString(const String& s) {}

int main() {
    printString(10); // 隐式转换:int → String,可能并非预期行为
}
上述调用会自动将整数`10`转换为`String`对象,这可能导致逻辑错误。通过添加`explicit`可阻止该行为:

class String {
public:
    explicit String(int size) { /* 分配指定大小的字符串缓冲区 */ }
};

int main() {
    // printString(10);        // 错误:禁止隐式转换
    printString(String(10));   // 正确:显式构造
}

何时应使用explicit

  • 所有只接受一个参数的构造函数都应考虑标记为explicit
  • 支持类型转换的构造函数若无需隐式调用,必须显式声明
  • 多个参数的构造函数可通过= delete或设计规避隐式转换风险
构造函数声明是否允许隐式转换
String(int size)是
explicit String(int size)否
使用`explicit`不仅增强了代码的清晰度,也减少了因自动转换引发的潜在bug,是现代C++编程中的最佳实践之一。

第二章:防止隐式类型转换的典型场景

2.1 单参数构造函数的隐式转换风险分析

在C++中,单参数构造函数可能引发隐式类型转换,导致非预期的对象构造行为。若未显式声明为 `explicit`,编译器将自动调用此类构造函数进行类型转换。
隐式转换示例

class Distance {
public:
    Distance(double meters) : meters_(meters) {}
private:
    double meters_;
};

void PrintDistance(Distance d) {
    // ...
}

// 调用时发生隐式转换
PrintDistance(5.0); // 合法但危险:double → Distance
上述代码中,double 类型值被自动转换为 Distance 对象,虽语法合法,但易引发逻辑错误。
风险规避策略
  • 使用 explicit 关键字阻止隐式转换
  • 对所有单参数构造函数进行显式声明
  • 通过静态工厂方法提供可控的构造路径

2.2 使用explicit避免自动类型提升的实战案例

在C++构造函数中,单参数构造函数会隐式触发类型转换,可能引发非预期行为。使用explicit关键字可禁止此类隐式转换,确保类型安全。
问题场景
假设定义一个表示容量的类Buffer,其构造函数接受整型参数:
class Buffer {
public:
    Buffer(int size) : size_(size) {}
private:
    int size_;
};
此时允许Buffer b = 1024;这样的写法,虽简洁但易误用。
显式构造解决方案
添加explicit关键字阻止隐式转换:
explicit Buffer(int size) : size_(size) {}
现在必须显式构造:Buffer b(1024);,杜绝了func(Buffer)被意外传入int的风险。 该机制在接口设计中尤为重要,能有效防止编译器自动进行不期望的类型提升,增强代码健壮性。

2.3 多参数构造函数中隐式转换的边界条件探讨

在C++等支持隐式类型转换的语言中,多参数构造函数可能触发非预期的类型转换行为。当构造函数未声明为explicit时,编译器可能尝试通过多个参数进行隐式转换。
构造函数隐式转换示例

class Point {
public:
    Point(int x, int y) : x_(x), y_(y) {}
private:
    int x_, y_;
};

void func(Point p) { /* ... */ }
func({1, 2}); // 合法:通过初始化列表隐式构造Point
上述代码中,{1, 2}被隐式转换为Point对象。这种行为依赖于参数类型的精确匹配和初始化列表的兼容性。
边界条件分析
  • 参数数量不匹配时,隐式转换将失败
  • 存在歧义的重载构造函数会导致编译错误
  • 用户定义的类型转换序列超过一个用户定义转换时被禁止

2.4 initializer_list与explicit的协同防御策略

在现代C++中,`std::initializer_list` 提供了便捷的初始化语法,但也可能引发隐式类型转换的安全隐患。通过结合 `explicit` 关键字,可有效防止非预期的构造函数调用。
显式构造避免隐式转换
class SafeVector {
public:
    explicit SafeVector(std::initializer_list list) {
        // 只允许显式列表初始化
        data.assign(list);
    }
private:
    std::vector data;
};
上述代码中,`explicit` 阻止了类似 SafeVector v = {1, 2, 3}; 的隐式转换,强制使用直接初始化语法,提升类型安全。
防御性编程实践
  • 所有接受 std::initializer_list 的构造函数应优先标记为 explicit
  • 避免重载导致的歧义,如同时提供 vector(int) 和 vector(initializer_list)
  • 在接口设计中,明确区分“容器初始化”与“数值构造”语义

2.5 编译器优化视角下的隐式转换拦截机制

在现代编译器设计中,隐式类型转换可能引入运行时开销或逻辑歧义。为了在保持语言表达力的同时提升性能,编译器通过静态分析拦截不必要的隐式转换。
拦截机制的触发条件
当表达式涉及复合类型操作时,编译器会检查类型匹配路径:
  • 是否存在显式重载运算符
  • 是否启用了严格类型模式
  • 目标上下文是否允许自动转型
代码示例与分析

int compute(double x) { return x * 2; }
void call() {
    short val = 10;
    compute(val); // 触发隐式提升
}
上述代码中,short 被隐式转换为 double。编译器若开启 -Wconversion,将生成警告,并可在优化阶段插入类型断言或直接拒绝转换。
优化策略对比
策略效果适用场景
静态拒绝消除运行时开销强类型安全要求高
插入断言保留兼容性渐进迁移代码库

第三章:提升接口安全性的设计实践

3.1 构造函数重载冲突中的显式调用优先级

在多构造函数重载的类设计中,当参数类型存在隐式转换路径时,编译器可能因无法确定最优匹配而引发重载解析冲突。此时,显式调用构造函数可消除歧义。
显式调用的优先级机制
当多个构造函数签名相近,如接受 int 和 double 时,传入 float 值将触发类型提升,导致匹配模糊。通过显式指定构造函数参数类型,可强制选择目标重载。

class Value {
public:
    Value(int v) { /* 初始化整型 */ }
    Value(double v) { /* 初始化浮点型 */ }
};

Value v1(5);        // 调用 int 构造函数
Value v2{5.0f};     // 显式使用 float 初始化,优先匹配 double 构造函数
上述代码中,5.0f 为 float 类型,虽可隐式转为 int 或 double,但编译器根据标准转换序列优先选择更精确的 double 构造函数。
最佳匹配规则
  • 精确匹配优先于类型提升
  • 显式类型初始化表达式(如花括号)增强重载解析明确性
  • 用户定义的转换序列优先级低于内置转换

3.2 接口清晰性与API可用性的权衡分析

在设计RESTful API时,接口清晰性强调语义明确、结构一致,而API可用性更关注调用效率与容错能力。两者常存在冲突,需合理权衡。
清晰性优先的设计示例
// GET /users/{id}/orders 返回订单列表
type OrderResponse struct {
    ID        string    `json:"id"`
    Status    string    `json:"status"`
    CreatedAt time.Time `json:"created_at"`
}
该结构字段命名清晰,类型明确,利于客户端理解。但若频繁调用,返回完整结构可能造成带宽浪费。
可用性优化策略
  • 支持字段过滤:通过?fields=id,status减少负载
  • 引入缓存机制:设置ETag或Last-Modified头提升响应速度
  • 版本控制:使用/v1/users保障向后兼容
最终应在文档完整性与灵活性之间取得平衡,提升整体开发体验。

3.3 在工厂模式中结合explicit保障对象构建安全

在C++开发中,工厂模式常用于解耦对象创建过程。若构造函数接受单参数且未声明为explicit,编译器可能执行隐式类型转换,引发意外的对象构造。
问题场景
考虑一个代表网络配置的类:
class NetworkConfig {
public:
    NetworkConfig(const std::string& ip) { /* 初始化 */ }
};
此时可通过NetworkConfig config = "192.168.1.1";隐式构造,易导致误用。
解决方案
将构造函数标记为explicit,禁止隐式转换:
explicit NetworkConfig(const std::string& ip);
在工厂方法中显式调用:
  • 确保对象只能通过工厂接口创建
  • 防止用户误用赋值语法触发隐式构造
此设计强化了对象生命周期管理的安全性与可控性。

第四章:现代C++中的高级应用模式

4.1 移动语义与explicit构造函数的兼容性设计

在现代C++中,移动语义与`explicit`构造函数的协同设计对资源管理至关重要。`explicit`关键字防止隐式转换,确保对象构造的明确性,而移动语义通过右值引用提升性能。
显式构造与移动的共存
即使构造函数声明为`explicit`,仍可参与移动操作。例如:

class Buffer {
public:
    explicit Buffer(size_t size) : data_(new char[size]), size_(size) {}
    Buffer(Buffer&& other) noexcept : data_(other.data_), size_(other.size_) {
        other.data_ = nullptr;
        other.size_ = 0;
    }
private:
    char* data_;
    size_t size_;
};
上述代码中,`explicit Buffer(size_t)`阻止了如`Buffer b = 1024;`的隐式调用,但不影响`std::move(b)`触发移动构造。移动构造函数不涉及隐式类型转换,因此不受`explicit`限制。
设计建议
  • 对单参数构造函数优先使用`explicit`,避免意外转换
  • 显式定义移动构造和移动赋值,确保资源高效转移
  • 注意编译器生成的隐式移动操作可能被`explicit`构造函数间接抑制

4.2 模板类中条件性使用explicit的技术实现

在C++模板编程中,`explicit`关键字的条件性使用可防止隐式类型转换,同时保持接口灵活性。通过结合SFINAE或`std::enable_if`,可根据类型特征决定构造函数是否显式。
条件性explicit的实现机制
利用`std::is_convertible_v`等类型特征,在模板特化中控制`explicit`的出现:
template<typename T>
class wrapper {
public:
    template<typename U = T, 
              std::enable_if_t<!std::is_integral_v<U>, int> = 0>
    explicit(!std::is_same_v<T, U>) // C++20起支持条件explicit
    wrapper(U u) : value(static_cast<T>(u)) {}
private:
    T value;
};
上述代码中,`explicit(!std::is_same_v)`表示仅当源类型与目标类型不同时才要求显式构造,避免不必要的显式调用。该特性自C++20起支持。
编译期判断的应用场景
  • 数值类型包装器中避免隐式窄化转换
  • 智能指针封装时防止意外的原始指针转换
  • 通用容器适配器中的安全构造路径控制

4.3 std::make_unique和std::make_shared的配合要点

在现代C++资源管理中,std::make_unique与std::make_shared是创建智能指针的推荐方式。它们不仅提升代码安全性,还优化了内存分配效率。
使用场景对比
  • std::make_unique用于独占所有权的场景,不可复制
  • std::make_shared适用于共享所有权,且性能更优
auto uniquePtr = std::make_unique<Widget>(42);
auto sharedPtr = std::make_shared<Widget>(42);
上述代码分别创建唯一和共享指针。make_shared内部将控制块与对象内存一并分配,减少一次内存分配开销。
避免混用陷阱
当需要从shared_ptr管理的对象返回shared_ptr时,若原为unique_ptr管理,则无法安全转换。应提前规划所有权模型,统一初始化方式,防止资源管理混乱。

4.4 constexpr构造函数与explicit的组合优化技巧

在现代C++中,将constexpr与explicit结合用于构造函数,可同时实现编译期计算和类型安全的显式转换。
语义清晰的常量初始化
使用explicit防止隐式转换,配合constexpr支持编译期构造,提升性能与安全性:
class Distance {
public:
    explicit constexpr Distance(double meters) : m_meters(meters) {}
    constexpr double getMeters() const { return m_meters; }
private:
    double m_meters;
};
上述代码中,构造函数被声明为explicit,避免了Distance d = 100.0;这类隐式转换;同时constexpr允许在编译期创建对象,如constexpr Distance maxLen(1000.0);。
优化场景对比
构造方式编译期求值隐式转换风险
普通构造否可能存在
constexpr + explicit是无

第五章:总结与架构设计建议

微服务拆分原则
在实际项目中,应基于业务边界进行服务划分。避免过早过度拆分导致运维复杂度上升。推荐遵循领域驱动设计(DDD)中的限界上下文概念,识别核心子域。
  • 用户管理、订单处理、支付结算应独立为服务
  • 共享数据库表必须避免,每个服务拥有独立数据存储
  • 跨服务通信优先采用异步消息机制,如 Kafka 或 RabbitMQ
高可用性设计
关键服务需部署多副本并配合 Kubernetes 的健康检查与自动重启策略。例如,在金融交易系统中,我们通过以下配置提升稳定性:
apiVersion: apps/v1
kind: Deployment
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    maxUnavailable: 1
  template:
    spec:
      containers:
      - name: payment-service
        resources:
          limits:
            memory: "512Mi"
            cpu: "500m"
监控与可观测性
集成 Prometheus + Grafana 实现指标采集,结合 Jaeger 进行分布式追踪。所有 API 接口需记录结构化日志,包含 trace_id、request_id 等上下文信息。
组件用途推荐工具
日志收集统一分析错误模式ELK Stack
链路追踪定位调用延迟瓶颈Jaeger
指标监控实时感知系统负载Prometheus
安全加固建议
API 网关层应强制启用 TLS 1.3,并校验 JWT 令牌。敏感操作需引入二次认证机制。数据库连接使用动态凭据,通过 Hashicorp Vault 注入环境变量。
什么是PON(无源光纤网络)、PON的发展及演进 全球知名媒体Omdia在光纤和铜缆接入设备预测报告中对2022年2月的预测显示,PON设备端口收入预计在2020年至2027年期间以12.3%的年复合增长率增长,到2027年将达到163亿美元,远高于2020年的82亿美元。 此前,Omdia有份报告称,在3月份举行的美国OFC展会中,众多 CSP 正在顺利部署 XGS PON(10G 对称),其他 CSP 专注于基于 GPON 的低速 FTTH 服务。另外关于25G PON 和 50G PON 之间的争论仍在继续,而Omdia 认为 25G PON 和 5 阅读详情

相关推荐

PX4算法解析:L1制导律

一、前沿 从今天开始,会陆续为大家解读开源飞控软件px4中使用到的各种算法,今天要讲述的是L1制导律,这是固定翼飞机进行路径跟踪的重要算法之一。这个算法是由MIT的研究人员提出,因为具有比较好的路径跟踪效果而得到广泛应用。在这之前,无人机在进行路径跟踪时一般采用基于侧偏距的PD控制器方法,至于为什么使用PD而不使用PID算法,那是因为位置环响应较慢,所以一般在外环采用PD算法,而在内环采用PID算...

weixin_44616080的博客 8256

C++ 中explicit的作用及用法(虽然简单,但是还是有用的)

C++ 中explicit的作用及用法(虽然简单,但是还是有用的)

weixin_57165154的博客 1万+

MPU6050运动中断唤醒STM32低功耗休眠模式实战

本文详细介绍了如何使用MPU6050运动中断唤醒STM32低功耗休眠模式的实战方案。通过配置MPU6050的运动检测中断作为STM32的唤醒源,实现设备在静止时进入低功耗Stop模式,运动时快速唤醒,大幅延长电池续航。涵盖硬件连接、软件配置、参数调试等关键步骤,并提供实际应用案例和优化建议。

rgv23456789的博客 703

【C++】explicit关键字详解(explicit关键字是什么? 为什么需要explicit关键字? 如何使用explicit 关键字)

在我们自己平时写 C++ 代码的时候,较少会用到 explicit关键字 。但是在C++相关的标准类库中,看到explicit关键字的频率还是很高的。既然出现的频率这么高,那么我们就来看看explicit关键字的作用到底是干什么的。

weixin_45031801的博客 8万+

OpenClaw Windows 安装指南

好的,我来一步一步带你在 Windows 上安装 OpenClaw。

m0_60605453的博客 550

手把手教你学simulink实例--基于Simulink的航空发动机控制系统设计与仿真

航空发动机是飞机的核心动力装置,其性能直接影响飞行器的安全性、经济性和可靠性。现代航空发动机控制系统需要具备高精度、快速响应和强鲁棒性的特点,以适应复杂的飞行环境和任务需求。本项目旨在使用MATLAB/Simulink平台,设计并实现一种适用于涡扇发动机的闭环控制系统,通过调节燃油流量、压气机叶片角度等控制变量,确保发动机在不同工况下稳定运行,并满足推力需求。

MHD0815的博客 275

explicit构造函数

转载于GGBeng大佬 链接在此 explicit构造函数 前面是扫盲部分,可直接看后面的精华部分。 扫盲 一、隐式的类类型转换 1. 转换构造函数 如果构造函数只接受一个实参,则它实际上定义了转换为此类类型的隐式转换机制 能通过一个实参调用的构造函数定义了一条从构造函数的参数类型向类类型隐式转换的规则 2. 从参数类型向类类型隐式转换的实例 //在Sales_data类中,接受string的构造函数和接受istream的构造函数分别定义了从这两种类型向Sales_data隐式转换的规则。 //即,在需要使

milaiko的博客 4571

搞定ESD(五):静电放电问题分析与调试

前面深入分析了静电放电的干扰机理、耦合路径,从现在开始将进入下一个大家非常关注的环节:静电放电问题分析与调试,掌握静电放电问题的分析方法,快速锁定敏感设备或者耦合路径,可以达到事半功倍的效果。

记得诚 2795

C++之explicit的作用介绍

@著作权归作者所有:来自优快云博客作者大胡子的艾娃的原创作品,如需转载,请注明出处https://blog.youkuaiyun.com/qq_43148810,否则将追究法律责任。 如有错误的地方欢迎指正,谢谢! 1、C++中的关键字explicit主要是用来修饰类的构造函数,被修饰的构造函数的类,不能发生相应的隐式类型转换,只能以显示的方式进行类型转换。类构造函数默认情况下声明为隐式的即implicit...

qq_43148810的博客 6395

【局部规划模块轨迹优化算法】EM_planner最大期望滚动优化算法

认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成长!本文先对EM_planner最大期望滚动优化算法做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章提示:以下是本篇文章正文内容。

qq_35635374的博客 760

JumpServer未授权访问漏洞 CVE-2023-42442

JumpServer 是全球首款完全开源的堡垒机, 使用GNU GPL v2.0 开源协议, 是符合4A 的专业运维审计系统。 JumpServer 使用Python / Django 进行开发。2021年1月15日,阿里云应急响应中心监控到开源堡垒机JumpServer发布更新,修复了一处远程命令执行漏洞。由于 JumpServer 某些接口未做授权限制,攻击者可构造恶意请求获取到日志文件获取敏感信息,或者执行相关API操作控制其中所有机器。

holyxp的博客 1424

使用explicit构造函数

使用explicit构造函数

qqrrjj2011的博客 1387

RK3588芯片CAN总线调试秘籍:SocketCAN与错误帧攻略

RK3588芯片在嵌入式领域凭借8nm工艺和强大性能成为核心控制器。本文详细介绍了其CAN总线配置流程,包括硬件连接、内核驱动配置及SocketCAN命令操作,并深入解析了CAN通信中的错误帧机制及分析方法。通过智能工厂案例,展示了从问题定位到解决方案的全过程,强调了稳定通信对工业应用的重要性。文章为RK3588的CAN总线应用提供了实用技术参考,并对未来智能诊断技术在该领域的应用进行了展望。

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 516

C++ explicit关键字使用全解析(资深架构师20年实战经验总结)

掌握C++隐式类型转换与explicit关键字的核心机制,避免构造函数误触发。详解单参数构造函数的隐式转换风险及explicit防护方法,提升代码安全性与可维护性,资深架构师实战经验总结,值得收藏

ProceSeed的博客 682

深度学习工具包 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")

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

C++ explicit构造函数避坑指南(资深架构师20年经验总结)

掌握C++ explicit的构造函数用法,避免隐式类型转换导致的编译错误与性能损耗。详解其适用场景、构造函数声明规范及在实际项目中的最佳实践,提升代码安全性与可维护性,值得收藏。

CompiGap的博客 866

efm32 入门.pdf

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

C++中的explicit关键字

在C++程序中很少有人去使用explicit关键字,不可否认,在平时的实践中确实很少能用的上。再说C++的功能强大,往往一个问题可以利用好几种C++特性去解决。但稍微留心一下就会发现现有的MFC库或者C++标准库中的相关类声明中explicit出现的频率是很高的。了解explicit关键字的功能及其使用对于我们阅读使用库是很有帮助的,而且在编写自己的代码时也可以尝试使用。既然C++语言提供这种特性

一步一步 13万+

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

C++中explicit构造函数的10大使用场景(资深架构师实战经验分享)

掌握explicit的构造函数防止隐式类型转换,提升代码安全性。涵盖单参数构造、STL容器、智能指针等10大应用场景,详解其设计原理与最佳实践。避免意外调用,增强程序健壮性,值得收藏。

QuickSolve的博客 282

C++ | explicit关键字

面对实例化对象时的隐式类型转换该如何处理,看看C++中的explicit关键字

做技术人 · 产优质博客 · 找好工作 3300

C++ explicit构造函数详解(避免隐式类型转换的5大实战场景)

掌握C++ explicit的构造函数用法,有效避免隐式类型转换带来的bug。详解5大实战场景,如单参数构造函数、类类型转换等,揭示如何通过explicit关键字提升代码安全性与可读性。防止意外转换,增强程序稳定性,值得收藏。

LiteTrans的博客 625

C++: 构造函数中的explicit详解

explicit在 C++ 中,explicit关键字用于修饰单参数构造函数或可以看作单参数的构造函数,阻止编译器进行隐式类型转换或拷贝初始化。默认情况下,单参数构造函数既可以显式调用,也可以被编译器用来进行隐式类型转换。explicit这个构造函数只能显式调用,不能用于隐式转换。explicit防止构造函数或转换运算符被隐式调用。在单参数构造函数和转换运算符中使用最为常见。自 C++11 起,还能用于;C++20 引入,进一步增强灵活性。默认加上explicit,除非你有充分理由允许隐式转换。

Ethan_Rich的博客 739

【C++ 修饰符关键字 explicit 】掌握C++中的explicit :构造函数行为和初始化综合指南

目录标题1. 引言1.1 为什么需要了解 `explicit`1.2 文章目标和主要内容概览2. C++ 构造函数简介2.1 什么是构造函数2.1.1 构造函数的基本语法2.1.2 重载构造函数2.2 构造函数的类型2.2.1 默认构造函数(Default Constructor)2.2.2 参数化构造函数(Parameterized Constructor)2.2.3 复制构造函数(Copy Constructor)2.2.4 移动构造函数(Move Constructor)

TyearLin的专栏 3340

C++的explicit

explicit用于防止构造函数的隐式调用和类型转换。它适用于单参数构造函数,帮助你控制对象的创建方式,避免潜在的错误。当你明确知道某个构造函数不应该被隐式调用时,使用explicit是一个好习惯。掌握explicit关键字能够让你编写更健壮和可控的代码,避免不必要的隐式转换带来的问题。这一行代码是用42作为参数来显式调用MyClass的构造函数,创建并初始化了一个名为obj的对象。explicit关键字保证了这种对象创建必须是显式的,避免了不必要的隐式转换。

weixin_44259499的博客 3736

C++20条件显式构造函数:explicit(bool)的完整指南

在现代C++编程中,类型安全一直是开发者关注的重点。C++20引入的`explicit(bool)`特性为我们带来了全新的条件显式构造函数能力,让类型转换更加智能和安全。这个强大的功能允许你在编译时根据类型特征动态决定构造函数是否需要显式调用,大大提升了代码的灵活性和表达能力。 ## 什么是条件显式构造函数? 条件显式构造函数是C++20中一个革命性的特性,它允许你基于模板参数的条件来决定构造

gitblog_00318的博客 711

C++: explicit的适用场合以及为什么要使用explicit

explicit是个C++关键子,但是关注过它的人远远没有其他关键字的多,但是往往忽略了它,就会在一些不经意的地方造成错误,而花费更多的时间去寻找. 看下下面这个例子: #include using namespace std; class A { public: A(int i = 5) { m_a = i; } private: i

闭上左眼看世界的博客 3万+

C++中的explicit关键字介绍

C++中的explicit关键字介绍

网络资源是无限的 2万+

C++构造函数explicit关键字

C++构造函数explicit关键字

上善若水 1516
上一篇: unordered_set哈希函数选型指南,避免退化为链表的关键一步
下一篇: 【C# 11字符串革命】:为什么你必须立即升级原始字符串用法?
CodeIsle
博客等级 码龄1年 145粉丝 1966原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值