C++ 基于struct实现Builder模式疑问:uint32_t未初始化与std::move用法是否正确
问题1:uint32_t age未初始化风险
你担心的问题确实存在。由于你的Person是聚合类型,默认初始化时内置类型成员不会执行零初始化,PersonBuilder内部的person_成员默认构造时,age会是不确定的垃圾值,如果你漏调用SetAge直接执行Build,拿到的age值是非法的,还可能触发未定义行为。
最简单的修复方案是直接给Person的age字段加默认初始值:
struct Person { std::string name; uint32_t age = 0; // 加默认初始值解决未初始化问题 std::vector<std::string> pet_names; };
也可以在PersonBuilder的构造函数里主动初始化age,效果是一样的。
问题2:Build方法中std::move(person_)的正确性
这个写法完全正确。person_是PersonBuilder的成员左值,用std::move转成右值之后,会触发Person的移动构造函数,相比拷贝构造省去了字符串、vector内部堆内存的拷贝开销,性能更好。而且Build执行完成后,当前PersonBuilder实例一般也不会再被使用,person_被移动后的合法不确定状态不会带来任何问题。
更优实现方案对比
要不要给struct Person加构造函数可以根据你的需求选择:
- 如果希望保留
Person的聚合类型特性(支持聚合初始化写法Person{"Tom", 18, {"dog", "cat"}}),就不要加构造函数,仅给字段加默认初始值即可,是轻量化的最优方案。 - 如果希望严格限制
Person的创建入口,强制所有Person实例都必须通过Builder构造、避免非法实例生成,可以把Person的构造函数设为私有,再将PersonBuilder设为友元类,从语法层面杜绝漏设字段的问题。
另外可选的优化点:你可以用C模板元编程或者C20的特性实现编译期必填字段检查,漏调用SetName、SetAge这类必填字段的设置方法时,直接在编译阶段报错,比运行期排查问题效率高很多。
内容的提问来源于stack exchange,提问作者senloa
相关产品推荐
相关产品推荐

