C++含std::vector结构体的拷贝构造与拷贝效率问题
MZEntry结构体C++问题解答
参考结构体定义如下:
struct MZEntry { uint32_t machineID; bool mode; uint32_t area; uint32_t occupancy; using ZList = std::vector<uint32_t>; ZList authorisationZ; ZList blockExceptionZ; void clear() { machineID = 0; mode = false; area = 0; occupancy = 0; authorisationZ.clear(); blockExceptionZ.clear(); } MZEntry(){ clear(); } MZEntry(const MZEntry& mzEntry) { machineID = mzEntry.machineID; mode = mzEntry.mode; area = mzEntry.area; occupancy = mzEntry.occupancy; authorisationZ = mzEntry.authorisationZ; blockExceptionZ = mzEntry.blockExceptionZ; } };
针对问题的解答如下:
问题1:显式声明上述拷贝构造函数是否存在实际收益?
没有任何实际收益。这份手写拷贝构造的执行逻辑和编译器默认生成的拷贝构造完全一致,既没有添加参数合法性校验,也没有针对特殊资源的自定义处理逻辑,纯粹是重复实现编译器本来就会自动生成的功能,反而会带来副作用:C++11及之后的标准中,只要用户显式声明了拷贝构造函数,编译器就不会自动生成移动构造、移动赋值运算符,后续对象转移场景无法走高效的移动语义,平白增加性能开销。问题2:定义两个MZEntry类型变量entry_1、entry_2,执行
entry_1 = entry_2赋值操作时,是否会将entry_2的所有字段(包含两个std::vector类型成员)完整拷贝到entry_1中?
会完整拷贝。当前代码只显式定义了拷贝构造函数,没有自定义拷贝赋值运算符,也没有将其标记为删除,编译器会自动生成默认的拷贝赋值运算符。默认逻辑为:对uint32_t、bool这类基础类型成员直接做值拷贝,对std::vector这类类类型成员,调用vector自身的拷贝赋值运算符做深拷贝,两个vector中存储的所有元素都会被完整复制到entry_1的对应成员中,不会出现浅拷贝导致的悬垂引用、重复释放问题。问题3:该使用场景下是否必须显式定义拷贝构造函数?当前实现的显式拷贝构造函数相比编译器默认生成的版本是否具备更高效率?
- 完全不需要显式定义拷贝构造函数。这个结构体的所有成员都是值语义类型:基础数值类型、bool、标准库vector,全部自带正确的拷贝、析构逻辑,不存在裸指针、手动管理的堆内存、系统句柄这类需要特殊处理的资源,编译器默认生成的拷贝构造、拷贝赋值、析构函数完全可以正确工作,符合RAII要求。
- 手写版本不仅效率没有提升,反而比编译器默认生成的版本更差。编译器自动生成的拷贝构造函数会直接在成员初始化阶段完成所有成员的拷贝构造:比如两个vector会直接在初始化时分配内存、拷贝源对象的元素;但手写版本执行时,会先调用所有成员的默认构造函数(两个vector先被初始化为空容器),进入构造函数体之后再执行赋值操作覆盖默认构造的结果,多了一轮默认初始化+赋值的冗余操作,存在额外开销。
内容的提问来源于stack exchange,提问作者liv2hak
相关产品推荐
相关产品推荐

