C++结构体部分显式构造导致编译异常分析

news2024/9/26 9:37:00

今天调试了一段代码如下

#include <iostream>
#include <shared_mutex>

#define SECT_NUM	2
#define DI_HIGH_PERM 2
#define DI_READ		1 
#define DI_WRITE	2
#define FMT_BIN    1

#define USER_PATH  "d:\\fafiles\\dbtest\\"

typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef unsigned char BYTE;

typedef struct{
    WORD  wID;
    WORD  wLen;
    WORD  wPerm;
    WORD  wRW;
    WORD  wOffset;
    WORD  wWrOp;
    WORD  wPnNum;
	DWORD dwBlockStart;	
	WORD  wBlockLen;
	DWORD dwBlockOffset;
	
	DWORD dwBlkIndex;
	BYTE  bBlkIndexNum;
	BYTE  bBlkIdIndexNum;
	BYTE  bInnerIndex;
}TItemDesc;//数据项描述

typedef struct{
	char*	   	pszBankName;
    char*      	pszPathName;
	char*      	pszBakPathName;
    TItemDesc* 	pItemDesc;
    DWORD      	dwItemNum;
    BYTE*  	   	pbDefault;
    DWORD  	   	dwDefaultSize;
	BYTE	   	bVer;
	WORD	   	wPnNum;
	bool	   	fUpdTime;
	WORD		wSaveInterv;
	std::shared_mutex shared_mtx_BankRW;
	BYTE*  	   	pbBankData{nullptr};
}TBankCtrl;

TItemDesc  g_TCommParaDesc[] =   //标准版
{ 
	//1
	{0x0001,   10, 		DI_HIGH_PERM,	DI_READ|DI_WRITE,	0, 		0,		FMT_BIN,		1},//Ver
	{0x8010,	6,		DI_HIGH_PERM,	DI_READ|DI_WRITE,	0, 		0,		FMT_BIN,		4 },//主站IP地址
	{0x8014,	6,		DI_HIGH_PERM,	DI_READ|DI_WRITE,	0, 		0,		FMT_BIN,		4 },//
	{0x8015,	16,		DI_HIGH_PERM,	DI_READ|DI_WRITE,	0, 		0,		FMT_BIN,		4 },//APN
};
BYTE g_bDefaultCommPara[] =  //标准版
{
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //ver
	//1
	0x5B, 0x07, 94, 240, 13, 10,			//0x8010 10.13.240.94 1883 主站地址+端口
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //0x8014 6 代理地址+端口
	'C', 'M', 'N', 'E', 'T', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //0x8015 16
};

TItemDesc  g_TUnitCommParaDesc[] =   //标准版
{
	//1
	{ 0x0002,   10,	DI_HIGH_PERM,	DI_READ | DI_WRITE,	0, 		0,	FMT_BIN,		1 },//Ver	
	{ 0x8900,	1,	DI_HIGH_PERM,	DI_READ | DI_WRITE,	0, 		0,	FMT_BIN,		10 },
	{ 0x8901,	1,	DI_HIGH_PERM,	DI_READ | DI_WRITE,	0, 		0,	FMT_BIN,		10 },
};

BYTE g_bDefaultUnitCommPara[] =  //标准版
{
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //ver

	0x00,
	0x00,
};

TBankCtrl g_Bank0Ctrl[SECT_NUM] = {
	//SECTION0
	{"sect0 Comm para",
	 USER_PATH"termnComm.cfg",
	 nullptr,									
	 g_TCommParaDesc,
	 sizeof(g_TCommParaDesc)/sizeof(TItemDesc),
	 g_bDefaultCommPara,						
	 sizeof(g_bDefaultCommPara),				
	 0x01,
	 1,
	 false,
	},

	//SECTION1
	{ "sect1 Unit-Comm para",					
	USER_PATH"UnitCommPara.cfg",				
	nullptr,									
	g_TUnitCommParaDesc,					    
	sizeof(g_TUnitCommParaDesc)/sizeof(TItemDesc),
	g_bDefaultUnitCommPara,						
	sizeof(g_bDefaultUnitCommPara),				
	0x01,
	1,
	false,
	},
};

int main()
{
	std::cout<<"test db !!"<<std::endl;
	getchar();
}

在VS上编译的时候提示:

1>e:\c++test\dbtest\dbtest1.cpp(109): error C2440: “初始化”: 无法从“initializer list”转换为“TBankCtrl”
1>  e:\c++test\dbtest\dbtest1.cpp(109): note: 无构造函数可以接受源类型,或构造函数重载决策不明确
========== 全部重新生成: 成功 0 个,失败 1 个,跳过 0 个 ==========

开始的时候以为是结构体和初始化数组不一致,反复对比无误,最后想到,可能是初始化异常导致,此处的初始化,除了在:TBankCtrl g_Bank0Ctrl[SECT_NUM]初始化,实际在结构体内部也有初始化:

 将该初始化去掉,改为

编译就正常了。

分析:

这是因为在 C++ 中,当一个结构体或类拥有至少一个构造函数时,它的默认构造函数会被自动生成。默认构造函数会尝试初始化所有成员变量,包括指针类型。对于指针类型,默认构造函数会将其初始化为一个未指定的值,通常是 nullptr。

当你将 TBankCtrl 中的最后一个变量从 BYTE* pbBankData{nullptr}; 修改为 BYTE* pbBankData; 时,你就在明示着不需要显式的构造函数,而依赖于编译器生成的默认构造函数,这也就避免了初始化列表中的问题。

结论:

C++使用struct(或者class)的时候,要么选择不默认任何成员,这样类会自动调用默认构造,默认构造会初始化成员变量,如果有部分不默认,那就写一个显示构造接口,或者使用数组批量给实例化(部分成员)对象赋值的时候,确保没有部分对象已经赋值了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/853852.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UE4 像素流 学习笔记

使用场景&#xff1a; 1、登录服务器&#xff0c;服务器上安装node.js Download | Node.js (nodejs.org) 点击该网址 点击Windows Installer 2、登录服务器&#xff0c;拷贝本地UE Pixel Streaming包到服务器 启用插件后重启该项目 3、登录服务器&#xff0c;修改\Sample\P…

MobXterm设置快捷键ctrl+v

问题&#xff1a; MobXterm是一个很好的ssh软件&#xff0c;粘贴按键反人性Shift Insert(Ins)&#xff0c;大部分人还是习惯CtrlV 原因&#xff1a;替换快捷键设置 CtrlV 方法&#xff1a;菜单setting->keybroad shotcuts->Paste in termainal

Hello,SpringBoot!

一、回顾什么是Spring Spring是一个开源框架&#xff0c;2003 年兴起的一个轻量级的Java 开发框架&#xff0c;作者&#xff1a;Rod Johnson Spring是为了解决企业级应用开发的复杂性而创建的&#xff0c;简化开发。 Spring是如何简化Java开发的 为了降低Java开发的复杂性…

金蝶,「起舞」在大模型时代

在过去的几年时间里&#xff0c;基于EBC的平台能力&#xff0c;金蝶已经走出了一个新的进化之路&#xff0c;这条路是对自身产品竞争力的重新构建&#xff0c;也更是对企业数字化转型需求的更大程度满足。 如今&#xff0c;苍穹GPT大模型更是让这种竞争力和服务力更向前一步。…

leetcode 881. 救生艇(java)

救生艇 leetcode 881. 救生艇题目描述代码 双指针算法 leetcode 881. 救生艇 难度 - 中等 leetcode 881. 救生艇 题目描述 给定数组 people 。people[i]表示第 i 个人的体重 &#xff0c;船的数量不限&#xff0c;每艘船可以承载的最大重量为 limit。 每艘船最多可同时载两人&a…

【Matlab】极限学习机-遗传算法(ELM-GA)函数极值寻优——非线性函数求极值

往期博客&#x1f449; 【Matlab】BP神经网络遗传算法(BP-GA)函数极值寻优——非线性函数求极值 【Matlab】GRNN神经网络遗传算法(GRNN-GA)函数极值寻优——非线性函数求极值 【Matlab】RBF神经网络遗传算法(RBF-GA)函数极值寻优——非线性函数求极值 【Matlab】Elman神经网络遗…

英国选举委员会泄露选民信息

The Hacker News 网站披露&#xff0c;2014 年至 2022 年间&#xff0c;英国选举委员会遭遇网络攻击&#xff0c;泄露大量选民的个人信息&#xff0c;目前委员会已经通知英国信息专员办公室。 英国选举委员会在推特上表示 2021 年 8 月&#xff0c;网络攻击者利用某安全漏洞&am…

MySQL索引1——索引基本概念与索引结构(B树、R树、Hash等)

目录 索引(INDEX)基本概念 索引结构分类 BTree树索引结构 Hash索引结构 Full-Text索引 R-Tree索引 索引(INDEX)基本概念 什么是索引 索引是帮助MySQL高效获取数据的有序数据结构 为数据库表中的某些列创建索引&#xff0c;就是对数据库表中某些列的值通过不同的数据结…

使用Flask.Request的方法和属性,获取get和post请求参数(二)

1、Flask中的request 在Python发送Post、Get等请求时&#xff0c;我们使用到requests库。Flask中有一个request库&#xff0c;有其特有的一些方法和属性&#xff0c;注意跟requests不是同一个。 2、Post请求&#xff1a;request.get_data() 用于服务端获取客户端请求数据。注…

JVM:运行时数据区域(白话文)

最近有时间在看一本<深入了解Java虚拟机>的书籍&#xff0c;这本书是一个中国人&#xff0c;名叫周志明的人写的。相比于其他翻译过来的技术书籍&#xff0c;这本书还是挺通俗易懂的。先前有和彬哥在聊&#xff0c;他说如果是自己一个人看的话会很枯燥&#xff0c;很难坚…

智慧城市美术效果Unity实现笔记流程

智慧城市美术效果Unity实现笔记流程&#xff1a; 参考 对标 效果图&#xff1a; 写实类-参考图&#xff1a; (以上均为网络搜索效果,有落叶大师&#xff0c;以及其他优秀开发者效果图参考) 未来类-参考图&#xff1a; 如上图所示,智慧城市基本分为 这两个大类&#xff0c;偏写…

辛苦了,你身边有一批优秀下属

领导者不是全知全能的&#xff0c;假如领导者啥都会&#xff0c;还要下属有何用&#xff1f;下属还有用武之地&#xff1f; 保罗赫塞说过&#xff1a;“领导力是通过与他人合作或通过他人协作实现组织目标的过程。” 一、日行一善 我们无法靠自己完成复杂的事情&#xff0c;…

在Python中定义Main函数

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 许多编程语言都有一个特殊的函数&#xff0c;当操作系统开始运行程序时会自动执行该函数。 这个函数通常被命名为main()&#xff0c;并且依据语言标准具有特定的返回类型和参数。 另一方面&#xff0c;Python解释器从文件…

DC-7靶机

DC-7靶机地址 同样的&#xff0c;把靶机跟kali放在同一网段&#xff0c;&#xff08;NAT模式&#xff09; 主机发现 arp-scan -l端口扫描 nmap -A -T4 -p- 192.168.80.13922端口开始&#xff0c;80端口开启 浏览器先访问一下靶机的80端口 熟悉的Drupal站点 先爆破一下目录…

【Linux】详解进程状态之僵尸进程——孤儿进程

目录 &#x1f31e;专栏导读 &#x1f31b;什么是进程 ⭐什么是PCB&#xff1f; &#x1f31b;查看进程 &#x1f31b;如何通过系统调用查看进程PID &#x1f31b;fork &#x1f31e;认识进程状态 &#x1f31b;查看进程状态 &#x1f31b;R状态 ⭐例如&#xff1a…

C 语言的 ctype.h 头文件

C 语言的 ctype.h 头文件包含了很多字符函数的函数原型, 可以专门用来处理一个字符, 这些函数都以一个字符作为实参. ctype.h 中的字符测试函数如表所示: 这些测试函数返回 0 或 1, 即 false 或 true. ctype.h 中的字符映射函数如表所示: 字符测试函数不会修改原始实参, 只会…

YOLOV5改进:更换为MPDIOU,实现有效涨点!

1.该文章属于YOLOV5/YOLOV7/YOLOV8改进专栏,包含大量的改进方式,主要以2023年的最新文章和2022年的文章提出改进方式。 2.提供更加详细的改进方法,如将注意力机制添加到网络的不同位置,便于做实验,也可以当做论文的创新点。 2.涨点效果:更换为MPDIOU,实现有效涨点! 目录…

C++代码生成静态LIB链接库及其调用方法

1、在进行C代码移植时可将CPP文件封装为静态lib链接库&#xff0c;本文章讲述了如何将cpp文件封装为lib文件。 2、假设有文件a.cpp、a.h、b.cpp、b.h以及main.cpp&#xff0c;假设main调用了b&#xff0c;b调用了a。现在需要将a.cpp以及b.cpp封装为a.lib以及b.lib。 3、在VS2…

Java8中forEach()里使用return的效果

先总结&#xff1a;使用forEach()处理集合时不能使用break和continue这两个方法&#xff0c;可以使用无返回值的return跳出此次循环&#xff0c;效果同标准for循环的continue。 首先&#xff0c;forEach()先对入参判空&#xff0c;然后使用增强for循环调用action.accept(t)&am…

VGG16模型详解

VGG16模型详解 0、VGG16介绍 VGG16是一种深度卷积神经网络&#xff0c;由牛津大学的研究团队于2014年开发。 VGG16在2014年的ImageNet Large Scale Visual Recognition Challenge (ILSVRC) 竞赛中取得了显著的成绩。它在图像分类任务中获得了当年的第二名&#xff0c;其准确…