• [技术干货] 基于CC2530(ZigBee)设计的景观照明控制系统+配套手机APP
    一、环境介绍编译集成开发环境: IARMCU: CC2530(ZigBee)编程语言: C语言手机APP: 采用QT设计,程序支持跨平台编译运行(Android、IOS、Windows、Linux都可以编译运行,对应平台上QT的环境搭建,之前博客已经发了文章讲解)硬件包含: 3套CC2530开发板(1个协调器、2个节点)、1个ESP8266串口WIFI、1个DHT11温湿度传感器、1个RGB多彩灯、1个BH1750光强度检测传感器.资料包里包含了: CC2530协调器源码、2个节点源码、手机APP源码、Windows上位机源码、手机APP可执行文件、IAR下载器驱动、IAR资料等等。二、功能介绍这是基于CC2530设计的景观照明控制系统,一共包含了3个CC2530节点(就是3块CC2530开发板)。下面将这个3个CC2530开发板称为A、B、C节点。A节点: 当做协调器、可以接收BC节点上传的数据;A模块配了一个ESP8266 WIFI模块,可以连接手机APP,将BC节点上传温湿度数据再上传给手机APP显示。如果A节点在一定时间内没有收到B、C节点的数据,就会通知手机APP,告诉用户,B、C节点已经掉线。B节点: 作为RGB多彩灯+温湿度检测节点,会根据当前温湿度调整当前RGB灯的颜色,用于告诉景区的游客,当前景区的温湿度情况,采集的温湿度也会通过CC2530传递给A节点。C节点: 光照强度检测+LED灯节点。 这里的LED灯就是模拟景区的路灯,手机APP可以控制LED灯的开关,如果是白天的时候,LED灯会自动关掉,天气变暗,自动打开。也可以设计时间,定时关灯。三、相关的硬件介绍3.1 DTH11 温湿度传感器DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性和卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个DHT11传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式存在OTP内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,使其成为该类应用中,在苛刻应用场合的最佳选择。产品为4针单排引脚封装,连接方便。3.2 ESP8266 WIFIESP8266系列无线模块是高性价比WIFI SOC模组,该系列模块支持标准的IEEE802.11b/g/n协议,内置完整的TCP/IP协议栈。用户可以使用该系列模块为现有的设备添加联网功能,也可以构建独立的网络控制器。能卓越ESP8266EX 芯片内置超低功耗 Tensilica L106 32 位 RISC 处理器,CPU 时钟速度最⾼可达 160 MHz,⽀持实时操作系统 (RTOS) 和 Wi-Fi 协议栈,可将⾼达 80% 的处理能⼒应用于编程和开发。高度集成ESP8266 芯片高度集成天线开关、射频巴伦、功率放大器、低噪声接收放大器、滤波器等射频模块。模组尺寸小巧,尤其适用于空间受限的产品设计。认证齐全RF 认证:SRRC、FCC、CE-RED、KCC、TELEC/MIC、IC 和 NCC 认证;环保认证:RoHS、REACH;可靠性认证:HTOL、HTSL、μHAST、TCT、ESD。丰富的产品应用ESP8266 模组既可以通过 ESP-AT 指令固件,为外部主机 MCU 提供 Wi-Fi 连接功能;也可以作为独立 Wi-Fi MCU 运行,用户通过基于 RTOS 的 SDK 开发带 Wi-Fi 连接功能的产品。用户可以轻松实现开箱即用的云连接、低功耗运行模式,以及包括 WPA3 在内的 Wi-Fi 安全支持等功能。3.3 CC2530CC2530 是用于2.4-GHz IEEE 802.15.4、ZigBee 和RF4CE 应用的一个真正的片上系统(SoC)解决方案。它能够以非常低的总的材料成本建立强大的网络节点。CC2530 结合了领先的RF 收发器的优良性能,业界标准的增强型8051 CPU,系统内可编程闪存,8-KB RAM 和许多其它强大的功能。CC2530 有四种不同的闪存版本:CC2530F32/64/128/256,分别具有32/64/128/256KB 的闪存。CC2530 具有不同的运行模式,使得它尤其适应超低功耗要求的系统。运行模式之间的转换时间短进一步确保了低能源消耗。CC2530F256 结合了德州仪器的业界领先的黄金单元ZigBee 协议栈(Z-Stack™),提供了一个强大和完整的ZigBee 解决方案。CC2530F64 结合了德州仪器的黄金单元RemoTI,更好地提供了一个强大和完整的ZigBee RF4CE 远程控制解决方案。3.4 RGB多彩灯颜色:全彩 红绿蓝三基色亮度:高亮电压:5V输入:数字电平三基色原理显示多重颜色通过PWM端口控制实现全彩显示3.5 BH1750** bh1750 是16位数字输出型,环境光强度传感器。**四、节点硬件+手机APP介绍4.1 C节点: 光敏传感器+LED灯控制4.2 B节点: 多彩灯+温湿度4.3 A节点: WIFI + APP4.4 手机APP界面效果五、手机APP上位机源码六、CC2530节点源码节点源码较多,下面就贴一些关键代码。6.1 uart.c#include "uart.h" /* 函数功能:串口0初始化 */ void Init_Uart0(void) { PERCFG&=~(1<<0); //串口0的引脚映射到位置1,即P0_2和P0_3 P0SEL|=0x3<<2; //将P0_2和P0_3端口设置成外设功能 U0BAUD = 216; //32MHz的系统时钟产生115200BPS的波特率 U0GCR&=~(0x1F<<0);//清空波特率指数 U0GCR|=11<<0; //32MHz的系统时钟产生115200BPS的波特率 U0UCR |= 0x80; //禁止流控,8位数据,清除缓冲器 U0CSR |= 0x3<<6; //选择UART模式,使能接收器 } /* 函数功能:UART0发送字符串函数 */ void UR0SendString(u8 *str) { while(*str!='') { U0DBUF = *str; //将要发送的1字节数据写入U0DBUF while(UTX0IF == 0);//等待数据发送完成 UTX0IF = 0; //清除发送完成标志,准备下一次发送 str++; } } /* 函数功能: 模仿printf风格的格式化打印功能 */ char USART0_PRINT_BUFF[200]; //格式化数据缓存数据 void USART0_Printf(const char *format,...) { char *str=NULL; /*1. 格式化转换*/ va_list ap; // va_list---->char * va_start(ap,format); //初始化参数列表 vsprintf(USART0_PRINT_BUFF, format, ap); //格式化打印 va_end(ap); //结束参数获取 /*2. 串口打印*/ str=USART0_PRINT_BUFF;//指针赋值 while(*str!='') { U0DBUF=*str; //发送一个字节的数据 str++; //指针自增,指向下一个数据 while(UTX0IF == 0);//等待数据发送完成 UTX0IF = 0; //清除发送完成标志,准备下一次发送 } }6.2 DHT11.c#include "dht11.h" #include "delay.h" #define DATA_PIN P0_7 //温湿度定义 uchar ucharFLAG,uchartemp; uchar shidu_shi,shidu_ge,wendu_shi,wendu_ge=4; uchar ucharT_data_H,ucharT_data_L,ucharRH_data_H,ucharRH_data_L,ucharcheckdata; uchar ucharT_data_H_temp,ucharT_data_L_temp,ucharRH_data_H_temp,ucharRH_data_L_temp,ucharcheckdata_temp; uchar ucharcomdata; //延时函数 void Delay_us() //1 us延时 { asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); } void Delay_10us() //10 us延时 { #if 0 Delay_us(); Delay_us(); Delay_us(); Delay_us(); Delay_us(); Delay_us(); Delay_us(); Delay_us(); Delay_us(); Delay_us(); #else int i = 10; while(i--); #endif } void Delay_ms(unsigned int Time)//n ms延时 { unsigned char i; while(Time--) { for(i=0;i<100;i++) Delay_10us(); } } //温湿度传感 void COM(void) // 温湿写入 { uchar i; for(i=0;i<8;i++) { ucharFLAG=2; while((!DATA_PIN)&&ucharFLAG++); Delay_10us(); Delay_10us(); Delay_10us(); uchartemp=0; if(DATA_PIN)uchartemp=1; ucharFLAG=2; while((DATA_PIN)&&ucharFLAG++); if(ucharFLAG==1)break; ucharcomdata<<=1; ucharcomdata|=uchartemp; } } void DHT11(void) //温湿传感启动 { DATA_PIN=0; Delay_ms(19); //>18MS DATA_PIN=1; P0DIR &= ~0x80; //重新配置IO口方向 Delay_10us(); Delay_10us(); Delay_10us(); Delay_10us(); if(!DATA_PIN) { ucharFLAG=2; while((!DATA_PIN)&&ucharFLAG++); ucharFLAG=2; while((DATA_PIN)&&ucharFLAG++); COM(); ucharRH_data_H_temp=ucharcomdata; COM(); ucharRH_data_L_temp=ucharcomdata; COM(); ucharT_data_H_temp=ucharcomdata; COM(); ucharT_data_L_temp=ucharcomdata; COM(); ucharcheckdata_temp=ucharcomdata; DATA_PIN=1; uchartemp=(ucharT_data_H_temp+ucharT_data_L_temp+ucharRH_data_H_temp+ucharRH_data_L_temp); if(uchartemp==ucharcheckdata_temp) { ucharRH_data_H=ucharRH_data_H_temp; ucharRH_data_L=ucharRH_data_L_temp; ucharT_data_H=ucharT_data_H_temp; ucharT_data_L=ucharT_data_L_temp; ucharcheckdata=ucharcheckdata_temp; } wendu_shi=ucharT_data_H/10; wendu_ge=ucharT_data_H; shidu_shi=ucharRH_data_H/10; shidu_ge=ucharRH_data_H; } else //没用成功读取,返回0 { wendu_shi=0; wendu_ge=0; shidu_shi=0; shidu_ge=0; } P0DIR |= 0x80; //IO口需要重新配置 }6.3 BH1750.c#include "bh1750.h" u8 Read_BH1750_Data() { unsigned char t0; unsigned char t1; unsigned char t; u8 r_s=0; IIC_Start(); //发送起始信号 IIC_WriteOneByteData(0x46); r_s=IIC_GetACK();//获取应答 if(r_s)USART0_Printf("error:1 "); IIC_WriteOneByteData(0x01); r_s=IIC_GetACK();//获取应答 if(r_s)USART0_Printf("error:2 "); IIC_Stop(); //停止信号 IIC_Start(); //发送起始信号 IIC_WriteOneByteData(0x46); r_s=IIC_GetACK();//获取应答 if(r_s)USART0_Printf("error:3 "); IIC_WriteOneByteData(0x01); r_s=IIC_GetACK();//获取应答 if(r_s)USART0_Printf("error:4 "); IIC_Stop(); //停止信号 IIC_Start(); //发送起始信号 IIC_WriteOneByteData(0x46); r_s=IIC_GetACK();//获取应答 if(r_s)USART0_Printf("error:5 "); IIC_WriteOneByteData(0x10); r_s=IIC_GetACK();//获取应答 if(r_s)USART0_Printf("error:6 "); IIC_Stop(); //停止信号 DelayMs(300); //等待 IIC_Start(); //发送起始信号 IIC_WriteOneByteData(0x47); r_s=IIC_GetACK();//获取应答 if(r_s)USART0_Printf("error:7 "); t0=IIC_ReadOneByteData(); //接收数据 IIC_SendACK(0); //发送应答信号 t1=IIC_ReadOneByteData(); //接收数据 IIC_SendACK(1); //发送非应答信号 IIC_Stop(); //停止信号 t=(((t0<<8)|t1)/1.2); return t; }
  • [技术干货] 【c++百日刷题计划】 ———— DAY9,奋战百天,带你熟练掌握基本算法-转载
    第一题 集合求和题目描述给定一个集合 s ss(集合元素数量 ≤ 30 \le 30≤30),求出此集合所有子集元素之和。输入格式集合中的元素(元素 ≤ 1000 \le 1000≤1000)输出格式s ss 所有子集元素之和。样例 #1样例输入 #12 31样例输出 #1101提示【样例解释】子集为:∅ , { 2 } , { 3 } , { 2 , 3 } \varnothing, \{ 2 \}, \{ 3 \}, \{ 2, 3 \}∅,{2},{3},{2,3},和为 2 + 3 + 2 + 3 = 10 2 + 3 + 2 + 3 = 102+3+2+3=10。【数据范围】对于 100 % 100 \%100% 的数据,1 ≤ ∣ s ∣ ≤ 30 1 \le \lvert s \rvert \le 301≤∣s∣≤30,1 ≤ s i ≤ 1000 1 \le s_i \le 10001≤s i​ ≤1000,s ss 所有子集元素之和 ≤ 10 18 \le {10}^{18}≤10 18 。解题思路1)数学推理题目。2)找规律发现,每个元素在 a 的每一个子集中出现的个数为2 n − 1 {2}^{n-1}2 n−1 。参考代码#include<bits/stdc++.h>using namespace std;int a[31];long long s=0;int main(){    int n=0;     {        s+=a[i];    }    s*=pow(2,n-2);    cout<<s;    return 0;}123456789101112131415第二题 [NOIP2004 普及组] 火星人题目描述人类终于登上了火星的土地并且见到了神秘的火星人。人类和火星人都无法理解对方的语言,但是我们的科学家发明了一种用数字交流的方法。这种交流方法是这样的,首先,火星人把一个非常大的数字告诉人类科学家,科学家破解这个数字的含义后,再把一个很小的数字加到这个大数上面,把结果告诉火星人,作为人类的回答。火星人用一种非常简单的方式来表示数字――掰手指。火星人只有一只手,但这只手上有成千上万的手指,这些手指排成一列,分别编号为 1 , 2 , 3 , ⋯ 1,2,3,\cdots1,2,3,⋯。火星人的任意两根手指都能随意交换位置,他们就是通过这方法计数的。一个火星人用一个人类的手演示了如何用手指计数。如果把五根手指――拇指、食指、中指、无名指和小指分别编号为 1 , 2 , 3 , 4 1,2,3,41,2,3,4 和 5 55,当它们按正常顺序排列时,形成了 5 55 位数 12345 1234512345,当你交换无名指和小指的位置时,会形成 5 55 位数 12354 1235412354,当你把五个手指的顺序完全颠倒时,会形成 54321 5432154321,在所有能够形成的 120 120120 个 5 55 位数中,12345 1234512345 最小,它表示 1 11;12354 1235412354 第二小,它表示 2 22;54321 5432154321 最大,它表示 120 120120。下表展示了只有 3 33 根手指时能够形成的 6 66 个 3 33 位数和它们代表的数字:三进制数    代表的数字123 123123    1 11132 132132    2 22213 213213    3 33231 231231    4 44312 312312    5 55321 321321    6 66现在你有幸成为了第一个和火星人交流的地球人。一个火星人会让你看他的手指,科学家会告诉你要加上去的很小的数。你的任务是,把火星人用手指表示的数与科学家告诉你的数相加,并根据相加的结果改变火星人手指的排列顺序。输入数据保证这个结果不会超出火星人手指能表示的范围。输入格式共三行。第一行一个正整数 N NN,表示火星人手指的数目(1 ≤ N ≤ 10000 1 \le N \le 100001≤N≤10000)。第二行是一个正整数 M MM,表示要加上去的小整数(1 ≤ M ≤ 100 1 \le M \le 1001≤M≤100)。下一行是 1 11 到 N NN 这 N NN 个整数的一个排列,用空格隔开,表示火星人手指的排列顺序。输出格式N NN 个整数,表示改变后的火星人手指的排列顺序。每两个相邻的数中间用一个空格分开,不能有多余的空格。样例 #1样例输入 #1531 2 3 4 5123样例输出 #11 2 4 5 31提示对于 30 % 30\%30% 的数据,N ≤ 15 N \le 15N≤15。对于 60 % 60\%60% 的数据,N ≤ 50 N \le 50N≤50。对于 100 % 100\%100% 的数据,N ≤ 10000 N \le 10000N≤10000。解题思路1)模拟深度优先搜索的全排列问题参考代码#include<bits/stdc++.h>using namespace std;int a[10005];bool used[10005]={0};int m,n;int main(){    cin>>n>>m;    for(int i=1;i<=n;i++)    {        cin>>a[i];        int x=a[i];        for(int j=1;j<=a[i];j++)            x-=used[j];        used[a[i]]=1;        a[i]=x-1;    }    a[n]+=m;    for(int i=n;i>0;i--)    {        a[i-1]+=a[i]/(n-i+1);        a[i]%=n-i+1;    }    memset(used,0,sizeof(used));    for(int i=1;i<=n;i++)    {        for(int j=0;j<=a[i];j++)            if(used[j])                a[i]++;        cout<<a[i]+1<<" ";        used[a[i]]=1;    }    return 0;}12345678910111213141516171819202122232425262728293031323334第三题 [NOIP2004 普及组] 最大约数和题目描述选取和不超过S的若干个不同的正整数,使得所有数的约数(不含它本身)之和最大。输入格式输入一个正整数S。输出格式输出最大的约数之和。样例 #1样例输入 #1111样例输出 #191提示样例说明取数字4和6,可以得到最大值(1+2)+(1+2+3)=9。数据规模S<=10001解题思路1)对数据进行预处理,求出每个数的约数和。2)简单的01背包问题。参考代码#include<bits/stdc++.h>using namespace std;int i,j,n,a[1001],dp[1001];int main(){    cin>>n;    for(i=1;i<=n/2;i++)        for(j=2;i*j<=n;j++)            a[i*j]+=i;    for(i=1;i<=n;i++)        for(j=i;j<=n;j++)            dp[j]=max(dp[j],dp[j-i]+a[i]);    cout<<dp[n];      return 0;}123456789101112131415第四题 [NOIP2004 普及组] 通天之分组背包题目背景直达通天路·小 A 历险记第二篇题目描述自 01 0101 背包问世之后,小 A 对此深感兴趣。一天,小 A 去远游,却发现他的背包不同于 01 0101 背包,他的物品大致可分为 k kk 组,每组中的物品相互冲突,现在,他想知道最大的利用价值是多少。输入格式两个数 m , n m,nm,n,表示一共有 n nn 件物品,总重量为 m mm。接下来 n nn 行,每行 3 33 个数 a i , b i , c i a_i,b_i,c_ia i​ ,b i​ ,c i​ ,表示物品的重量,利用价值,所属组数。输出格式一个数,最大的利用价值。样例 #1样例输入 #145 310 10 110 5 150 400 21234样例输出 #1101提示1 ≤ m , n ≤ 1000 1 \leq m, n \leq 10001≤m,n≤1000。解题思路1)分组背包问题。2)直接枚举每个组,再在每个组里进行01背包。参考代码#include<bits/stdc++.h>using namespace std;long long dp[1050];int a[1050],b[1050],c,C[1050];int g[205][205];int main(){    int m,n;    cin>>m>>n;    int zu=0;    for(int i=1;i<=n;i++)    {                cin>>a[i]>>b[i]>>c;        zu=max(zu,c);        C[c]++;        g[c][C[c]]=i;    }        for(int i=1;i<=zu;i++)    {        for(int j=m;j>=0;j--)        {            for(int k=1;k<=C[i];k++)            {                if(j>=a[g[i][k]])                {                    dp[j]=max(dp[j],dp[j-a[g[i][k]]]+b[g[i][k]]);                }            }        }    }    cout<<dp[m];    return 0;}————————————————版权声明:本文为CSDN博主「锡兰_CC」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/Ceylan__/article/details/126246543
  • [技术干货] C/C++后端实习经验大礼包-转载
    C/C++后端实习经验大礼包文章目录C/C++后端实习经验大礼包一、前言二、实习面试宝典1.自我介绍2.深挖个人项目(多个问题不同角度)3.有用过STL吗?常用哪些STL?4.介绍一下你对STL的理解5.深挖STL底层6.Qt有接触过吗?Qt下Tcp通信的整个流程是怎么样的?7.设计模式的问题8.编译原理的简单问题9.讲一下dijkstra算法10.谈一下你对STL的理解11.STL的使用场景12.C++11语法熟悉吗13.工程里面的回溯是什么?14.Widget::Widget(QWidget *parent) :QWidget(parent)什么意思15.算法题:跳台阶(找规律可以发现是个斐波那契数列)16.算法题: 餐厅(区间贪心)17.反问面试官环节三、实习工作分享1.实习专有名词及分析篇1.1SDK:软件开发工具包(Software Development Kit)1.2API:应用程序接口(Application Programming Interface)举例:windows串口通信函数API1.3上位机1.4下位机1.5上位机与下位机区别四、总结一、前言这篇文章是C/C++后端实习经验大礼包的第一弹,后面会持续更新,谢谢大家支持~~撒花,前面说过博主目前在一家互联网公司实习,今天给大家带来第一弹C/C++后端实习经验大礼包,希望大家喜欢。123二、实习面试宝典流程:投简历->简历筛选->笔试->技术电话面->技术视频面->hr面(有些公司可能在中间环节比较多,比如两次技术电话面,两次技术视频面等,视频面多为主管之类的,ps:主管面会参考之前的部门对你面试的评价)1.自我介绍2.深挖个人项目(多个问题不同角度)3.有用过STL吗?常用哪些STL?回答:用过,平时用的比较多,常用vector,map,unordered_map,stack,queue,deque,set,multiset,unordered_set,priority_queue,bitset,list之类的4.介绍一下你对STL的理解回答:STL就是标准模板库,可以提高程序的开发效率和复用性。5.深挖STL底层vector:底层存储是一个可变大小的数组,支持O(1)的随机访问,在尾部之外的位置插入和删除操作时间复杂度是 O(n);deque:双端队列,支持O(1)随机访问在头部和尾部之外的位置插入和删除的时间复杂度是O(n);list: 双向链表,不支持随机访问,只支持顺序访问,在任意位置的插入和删除速度很快;forward_list:单向链表;array是固定大小的数组(vector是可变大小的数组);string:与vector类似,可以理解为特殊的vector,专门用来存储字符,支持随机访问,在尾部之外的位置插入的时间复杂度是O(n);6.Qt有接触过吗?Qt下Tcp通信的整个流程是怎么样的?有的,主要从服务器端和客户端两方面介绍:1.服务器端创建用于监听的套接字(Socket)Socket可以看成在两个程序进行通讯连接中的一个端点,一个程序将一段信息写入Socket中,该Socket将这段信息发送给另外一个Socket中,使这段信息能传送到其他程序中。给套接字设置监听如果有连接到来, 监听的套接字会发出信号newConnected接收连接, 通过nextPendingConnection()函数, 返回一个QTcpSocket类型的套接字对象(用于通信)使用用于通信的套接字对象通信1 发送数据: write2. 接收数据: readAll/read客户端方面:创建用于通信的套接字连接服务器: connectToHost连接成功与服务器通信1 发送数据: write2.接收数据: readAll/read7.设计模式的问题后面我会专门写文章来讲8.编译原理的简单问题后面我会专门写文章来讲9.讲一下dijkstra算法回答:。dijkstra算法是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。时间复杂度:朴素版写法O(V方) 进阶写法:基于优先队列的写法(适用于稀疏图)总复杂度为 O(V log E)Edge:边 Vertex:顶点10.谈一下你对STL的理解C++ STL 做为C++的一个标准类库,包含了复用性最高的数据结构(容器)与算法(模板函数)。STL的容器可以分为以下几个大类:一:序列容器,有vector, list, deque,string.二:关联容器可以分为 set(集合)和 map(映射表)两大类,及其衍生体 multiset 和 multimap。这些容器的底层机制均以 RB-tree(红黑树)实现。RB-tree 也是一个独立容器,但并不开放使用。SGI STL 还提供一个不在标准规格的关联式容器 hash_table(散列表),以及以 hash_table 为底层机制而完成的 hash_set散列集合、hash_map散列映射表、hash_multiset散列多键集合、hash_multimap散列多键映射表。关联容器,类似关联式数据库,每个元素都有一个键值key和一个实值value。关联式容器的内部结构是一个平衡二叉树,包括 AVL-tree、RB-tree、AA-tree,STl 中运用的是 RB-tree红黑树。11.STL的使用场景vector(可变长的动态数组)适用场景:需要快速查找,不需要频繁插入/删除的场景string:string 类型支持长度可变的字符串,实际上就是vector,便于程序员操作字符串的类库。也可以认为string是一个类:string封装了char* ,管理这个字符串,是一个char* 型的容器;array:数组 使用场景:类似vector,比数组更安全(不担心越界),但是内容在栈上,且属于定长容器。deque:(double-ended queue,双端队列)是一种具有队列和栈的性质的数据结构。双端队列中的元素可以从两端弹出,其限定插入和删除操作在表的两端进行。使用场景:头尾增删元素很快,随机访问比vector慢一点,因为内部处理堆跳转。中间插入和删除效率交较高。但因为他是list和vector的结合体,出场次数不多。forward_list:使用场景:需要list的优势,但只要向前迭代list:需要频繁插入/删除,不需要快速查找queue:FIFO(先进先出)~( First Input First Output)。底层容器可以是list或deque。set/multiset:需要元素有序,查找/删除/插入性能一样。红黑树效率都是O(logN)。即使是几个亿的内容,最多也查几十次。map/multimap 映射/多重映射:需要key有序将值关联到key,O(logN)查找/删除/插入性能一样12.C++11语法熟悉吗回答:还行,之后问了std::function,我回答是std::function是一个函数包装模板,可以包装下列这几种可调用元素类型:函数、函数指针、类成员函数指针或任意类型的函数对象(例如定义了operator()操作并拥有函数闭包)。std::function对象可被拷贝和转移,并且可以使用指定的调用特征来直接调用目标元素。当std::function对象未包裹任何实际的可调用元素,调用该std::function对象将抛出std::bad_function_call异常。13.工程里面的回溯是什么?回答:用git一直备份版本有需要就回退一下14.Widget::Widget(QWidget *parent) :QWidget(parent)什么意思由于构造函数是指在创建一个新对象的时候,自动执行,因此通常用来实现一些默认操作。此处“Widget::Widget(QWidget *parent) ”定义派生类的构造函数;:QWidget(parent)基类的有参构造函数最终达到:调用基类的有参构造函数,实现对象树上基类的功能15.算法题:跳台阶(找规律可以发现是个斐波那契数列)一个楼梯共有 n 级台阶,每次可以走一级或者两级,问从第 0 级台阶走到第 n 级台阶一共有多少种方案。输入格式共一行,包含一个整数 n。输出格式共一行,包含一个整数,表示方案数。数据范围1≤n≤15输入样例:5输出样例:8#include<bits/stdc++.h>using namespace std;int a=1,b=2,c;int main(){    int n;    cin>>n;    int w=n-2;    if(n==1) cout<<1;    else if(n==2) cout<<2;    else    {        while(w--)        {            c=a+b;            a=b,b=c;        }        cout<<b;    }}123456789101112131415161718192016.算法题: 餐厅(区间贪心)一家餐厅收到了 n 个客人的预约订单。每个订单都有开始时间和结束时间。对于每个订单,餐厅有权利接单,也有权利拒单。接受的订单,两两之间不得有任何时间交集,甚至不得有时刻交集,即如果一个订单的开始时间和另一个订单的结束时间相同,则两订单也不得同时接受。为了赚更多钱,餐厅需要尽可能多的接单。请问,餐厅最多可以接多少单?输入格式第一行包含一个整数 n。接下来 n 行,每行包含两个整数 l,r,表示一个订单的开始时间和结束时间。输出格式输出可以接受的最大订单数量。数据范围1≤n≤5×105,1≤l≤r≤109输入样例1:27 114 7输出样例1:1输入样例2:51 22 33 44 55 6输出样例2:3输入样例3:64 81 54 72 51 36 8输出样例3:2#include<bits/stdc++.h>using namespace std;struct node{    int l,r;};int n;bool cmp(node x,node y){    return x.r<y.r;}int main(){    cin>>n;    node a[n+1];    int i;    for(i=0;i<n;i++)    {        cin>>a[i].l>>a[i].r;    }    sort(a,a+n,cmp);    int temp=a[0].r;    int tot=1;    for(i=1;i<n;i++)    {        if(a[i].l>temp)        {            temp=a[i].r;            tot++;        }    }    cout<<tot;}123456789101112131415161718192021222324252627282930313217.反问面试官环节自由发挥即可,可以提前准备一些大众问题和自己关心的问题。三、实习工作分享1.实习专有名词及分析篇实习中你肯定会接触到很多自己没不熟悉的名词,在这里算法小学徒给大家分享一些cpp后端专有名词的解释:1.1SDK:软件开发工具包(Software Development Kit)软件开发工具包一般都是一些软件工程师为特定的软件包、软件框架、硬件平台、操作系统等建立应用软件时的开发工具的集合。SDK相当于是一个开发者集成的环境,作为APP供应链中重要的一环,在提升App兼容性和灵活性、节约开发成本方面表现卓著。一个产品想实现某些特定功能如消息推送,便可以找到相关的第三方SDK,工程师直接接入SDK,不用再重新开发。这样,工程师可以将更多的时间和精力投入到其他产品业务相关功能的开发上。1.2API:应用程序接口(Application Programming Interface)API又称为应用编程接口,就是软件系统不同组成部分衔接的约定。由于近年来软件的规模日益庞大,常常需要把复杂的系统划分成小的组成部分,编程接口的设计十分重要。程序设计的实践中,编程接口的设计首先要使软件系统的职责得到合理划分。良好的接口设计可以降低系统各部分的相互依赖,提高组成单元的内聚性,降低组成单元间的耦合程度,从而提高系统的维护性和扩展性。简单地说:API就是接口,就是通道,负责一个程序和其他软件的沟通,本质是预先定义的函数。举例:windows串口通信函数API1.CreateFile - 打开串口;2.SetupComm-初始化一个指定的通信设备的通信参数3.ReadFile - 读数据;4.WriteFile - 写数据;5.CloseHandle - 关闭串口;6.GetCommState - 取得串口当前状态;7.SetCommState - 设置串口状态;8.PurgeComm - 清除串口缓冲区 ;9.ClearCommError - 清除串口错误或者读取串口现在的状态;10.SetCommMask - 设置串口通信事件;1.3上位机上位机是指可以直接发出操控命令的计算机。1.4下位机下位机是直接控制设备获取设备状况的计算机。1.5上位机与下位机区别1.上位机一般是集中管理监控机,下位机是指现场直接控制器或控制机。上位机面向管理级用户,下位机面向底层设备控制。2.上位机:上位监视系统,一般为计算机系统(监控软件;下位机:控制系统的现场执行系统,一般为PLC等设备。3上位机是指工业控制中位于较高层次的计算机,一般是指电脑;而下位机是直接控制设备获取设备状况的的计算机,一般是指PLC/单片机之类的。4.经验:通常工控机,工作站,触摸屏作为上位机;而通信控制PLC,单片机等作为下位机,从而控制相关设备元件和驱动装置。四、总结后面博主会继续为大家带来 C/C++后端实习经验大礼包的其他内容,希望大家喜欢,撒花~~,另外根据博主的亲身实习经验,自学能力不管是面试还是实习过程中都非常受青睐, 程序员行业是一个需要终身学习的行业,大部分时间别人教你的东西只能作为一个参考,而且自学这种能力可以让人感觉到了无限的可能和创造性,跨越认识边界,不受限制的感觉真的很奇妙每日一句:不是因为有希望才去努力,而是努力了,才能看到希望。成功重在努力与坚持,抓住时机,就趁现在!与大家共勉!!!————————————————版权声明:本文为CSDN博主「算法小学徒」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/wyhplus/article/details/125771094
  • [技术干货] C/C++ 指针小笔记-转载
    如果想要更详细的了解指针原理、用途,请自行阅读《The C Programming Language》第 5 章。指针是什么指针其实就是一个包含一个变量的地址的变量。如何定义指针定义指针的方式很简单:类型 *指针名称;即可。比如来声明一个变量名为a,类型为int的指针:int *a;1也就是比平时声明变量多了一个型号*。但是这里需要注意的是,声明时候的*a表示的是指针a包含的内存地址指向的内容,而a包含的则是地址。 这个地址开始的一部分连续的空间将会划分给指针,以供存储地址,划出的大小由类型int决定,一般int为 2 个字节(这里的一个字节在有些英文文档中被称为“cell”)。如何获取一个变量的地址刚才说到指针其实就是一个包含一个变量的地址的变量。那么如何获取一个变量的地址呢?这样才可以给指针赋值。方法很简单,使用&符号,如下(a就是上文声明的指针):a=&b;1通过以上表达式,就将变量b的地址赋值给指针a,如果这时候使用*a输出,就会发现输出的是b的值。而且修改b,输出*a的值也会发生改变。如果a并不是指针,那么变量a将会以十六进制存储变量b的地址(一般是十六进制,有些环境、设备可能会有不同)。下面展示输出一个变量地址的方法:#include <stdio.h>int main(){    int a=10;        printf("%x\n",&a);        return 0;}12345678910输出结果如下:bfeff2c8Program ended with exit code: 012可以看到,第一行的bfeff2c8就是变量a的地址。赋值给一个指针指针只负责存储地址,具体的值还是由变量存储。所以赋值给指针,就是将一个变量的地址赋值给它。如下:#include <stdio.h>int main(){    int a=10;    int *b;        b=&a;        printf("%d\n",*b);        return 0;}12345678910111213输出:10Program ended with exit code: 012指针的用途听了上述描述,可能你会觉得指针的作用好像就是新建了一个软连接(symbolic link)或者创建了一个别名(alias)。但是指针最大的作用其实是搭配数组使用。通过指针来使用数组因为一个数组的地址其实是数组第一个元素的地址,而数组在地址上是连续存放的,所以可以对地址加 1 来实现控制数组。如下(实际运行的时候可能会提醒,但是这里出于研究目的忽略提醒):#include <stdio.h>int main(){    int a[5]={1,2,3,4,5};    int *b;        b=&a;        printf("数组地址:%x\n",&a);    printf("数组第一个元素:%d\n",*b);    b=b+1;    printf("是不是数组第二个元素:%d\n",*b);        return 0;}12345678910111213141516输出:数组地址:bfeff2b0数组第一个元素:1是不是数组第二个元素:2Program ended with exit code: 01234这里说明一下,如果在开发过程中,指针指向数组的话,请使用b=&a[0];,这样不会出现提醒。字符串和指针字符串也是数组的一部分,所以也可以使用指针来实现一些功能,例如对比字符串(这个虽然不用指针也能写,但是使用指针的话,代码会变得更简洁)。下面来演示一下指针访问字符串的例子(记得把指针类型换一下,换成char,不然int存放的会是 ASCII编码,而不是字符串的内存地址):#include <stdio.h>int main(){    char a[20]="Hello! World!";    char *b;        b=&a[0];        printf("字符串的地址:%x\n",&a);    printf("字符串的第一个字符:%c\n",*b);    b=b+5;    printf("字符串的第六个字符:%c\n",*b);        return 0;}12345678910111213141516输出:字符串的地址:bfeff2b0字符串的第一个字符:H字符串的第二个字符:!Program ended with exit code: 01234其他用途还有一些其他的用途,但是有上述的知识也不用过多解释了,讲一下思路即可。更多维度的数组C 语言支持二维数组,但是有时候需要更多维度,那么就需要使用指针来嵌套数组,这样可以实现更多维度的数组。一般就是将指向多个数组的多个指针存放在一个数组中,然后通过上述方法来使用。处理命令选项这个一般使用不多,因为现在也没多少人使用命令行,都用图形化了,但是我还是要说一下。先看一下我的另一篇博客《C语言中函数main的参数argc和argv是什么》。argv是一个指向一个字符串数组的指针,数组包含了参数,每个字符串就是一个参数,最后一个元素为0。不过一般习惯使用多级指针来操作字符串。这里介绍一下,一般的命令行程序,使用起来的命令如下:程序名 -短选项 --长选项 内容1短选项为-加一个字母,长选项一般为--加一个单词。现在有些程序的短选项会省略-。短选项一般可以写到一起,举个例子:ls -a -f也可以写成ls -af。而这一功能的实现就需要使用指针(首先这是个存放了指向字符串指针的数组,其次指针真的更方便)。————————————————版权声明:本文为CSDN博主「zhonguncle」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/qq_33919450/article/details/126129081
  • [技术干货] 、Python 比 C++ 慢 8 倍、29 倍?-转载
    整理 | 苏宓出品 | CSDN(ID:CSDNnews)近日,来自多伦多大学和 YScope 公司(为软件系统提供创新的日志管理和故障排除工具。由一群计算机工程教授和博士创立)的 David Lion、多伦多大学 Adrian Chiu 和 Michael Stumm、多伦多大学和 YScope 公司 Ding Yuan 共同发布了一份《调查托管语言的运行时性能:为什么 JavaScript 和 Python 比 C++ 慢了 8 倍和 29 倍,而 Java 和 Go 却能更快》(https://www.usenix.org/system/files/atc22-lion.pdf)的论文分析报告,深度剖析了不同编程语言运行时在代码开发中真实的性能情况,由此方便开发者可以精确地测量执行任何字节码指令所花费的时间等。性能是系统软件不得不面对的挑战在报告中,研究人员指出,自 2015 年以来,具有集成运行时环境的编程语言越来越受欢迎,其中,全球知名的代码托管平台 GitHub 上最受欢迎的三种语言分别是 JavaScript、Java 和 Python。作为开发利器,编程语言帮助开发者快速构建各种应用程序和服务,也极大地提高了生产力。同时,这些语言自身也提供了各种功能,如动态类型检查、带有垃圾收集的内存管理,以及动态内存安全检查等等。为此,研究人员用「托管语言」(managed languages)专业术语来指代这些类型的编程语言。现实来看,托管语言越来越多地被用于实现性能至关重要的系统软件上,如Hadoop 和 Spark 都在 Java 虚拟机(JVM)上运行,因为它们分别用 Java 和 Scala 实现;Kubernetes、etcd(分布式键值存储)和 M3(由 Uber 建立的分布式时间序列数据库和查询引擎)都是用 Go 实现的。当前,甚至连操作系统(OS)的内核 Biscuit 也是用 Go 实现的 。Openstack、Paypal、Instagram 和 Dropbox 都大量使用 Python,其中,Python 是 Dropbox "在后台服务和桌面客户端应用中使用最广泛的语言",在一个存储库中就有近 400 万行 Python 代码;JavaScript 也被用于 Facebook 的 Bladerunner pub/sub 系统的性能关键路径中。在开发过程中,编程语言的性能在一开始很少会被考虑到项目中,部分原因是不少开发者认为性能问题可以在以后慢慢去解决,也许可以通过简单地增加硬件来进行横向扩展。不过,随着代码产品或服务使用规模的扩大,服务变得越来越慢或者硬件成本变高,性能成为一个不容忽视的问题。这也是为什么 Stream 要放弃了 Python 而改用 Go、 Discord 从 Go 切换到 Rust、Twitter 从 Ruby on Rails 切换到 Scala 和 Java 的主要原因。不少开发者往往为了提升性能,想破脑袋,但现实只有两条路,一条是从现有的代码中想尽办法尽可能地做优化,另一条是思考使用的编程语言是否已经达到了性能极限,看看有没有必要将旧的代码移植到一个新的性能更高的语言上。为了彻底解开系统软件中不同编程语言导致的性能问题,研究人员决定以 C++ 为极限,对 Java、Go、JavaScript 和 Python 四种编程,还有应用最广泛的运行时系统 CPython、OpenJDK。Node.js 与 JavaScript 的 V8 引擎进行深入的定量性能分析。同时,研究人员还从头开始建立了 6 个应用程序,并创建了一个名为 LangBench 基准(https://github.com/topics/langbench)。这些应用程序涵盖了各种不同的计算强度、内存使用、网络和磁盘 I/O 强度以及可用的并发性的应用场景等复杂性。对此,研究人员全面分析了它们的完成时间、资源使用和可扩展性。测试方法值得一提的是,研究人员指出,这份论文没有也不可能全面地回答与语言运行时的性能有关的每一个问题。本文只是评估了四种语言的运行时,而且对于每种语言,只评估了最广泛使用的实现。此外,研究人员只在一个单一的操作系统/硬件堆栈上运行了工作负载。其研究结果与使用的基准有关,这些基准模拟了现实生活中的应用,但可能不代表广泛的应用。在测试方法上,研究人员在两台内部服务器上进行了实验,每台服务器有 2 个Xeon E5-2630V3、16 个虚拟核心、2.4GHz CPU、256GB DDR4 内存和两个 7200 RPM 硬盘。它们运行的系统是 Linux 4.15.0,并通过 10Gbps 的互联网络连接。对于 C++ 程序,研究人员使用的是 GCC 9.3.0 根据 C++17 标准用 -O3 进行编译。对于 OpenJDK 13、CPython 3.8.1 和Go 1.14.1 ,其使用了各自语言的参考实现。同时,使用 Node.js 13.12.0 和 V8 7.9.317.25 版本。研究人员对每个基准进行了 5 次测试,取平均值。其中,在运行键-值存储、日志分析器和文件服务器的基准时,client 和 worker 线程的数量从 1 到 1024 不等。对于 OpenJDK 和 V8 来说,最小的内存量是通过确定不会导致崩溃的第一个堆配置来设置的;对于 Go 来说,GOGC 被设置为5%。然后研究人员不断增加堆的设置,直到性能不再提高。其使用第一个设置的结果(即最小的堆大小)得出最佳性能。对于日志解析器和文件服务器基准,所用的日志文件被存储在一个复制系数为 2 的分布式文件系统上。 在运行每个基准之前,研究人员都清除了 Linux 的页面缓存,以保证测试准确性。其中,优化的 GCC 平均速度最快,Go 和 OpenJDK 紧随其后,比 GCC 慢了  1.30 倍和 1.43 倍。令人印象深刻的是,在 12 项基准测试中,Go 和 OpenJDK 有 3 项超过了优化的 GCC。总体而言,研究人员发现 V8 / Node.js 和 CPython 表现最差,执行应用程序的平均速度分别比 C++ 应用程序慢 8.01 倍和 29.50 倍,这意味着运行时下,JavaScript、Python 要比 C++ 慢这么多。更糟糕的是,这两个运行时上的应用程序扩展性很差,因为它们无法有效地利用多个内核。在极端情况下,CPython 比 GCC 慢了 129.66 倍(在排序基准中)。V8/Node.js 和 CPython 只有在工作负载受到磁盘 I/O 的瓶颈时,即在文件服务器基准中,才与 GCC 有竞争力。相比之下,OpenJDK 和 Go 应用程序即 Java 和 Go 语言比 C++ 更具有性能竞争力,运行速度仅慢了 1.43 倍和 1.30 倍,并且可以轻松扩展到多个内核。在一些应用中,OpenJDK 和 Go 的性能超过了 C++ 的同类产品。更多完整报告内容详见:https://www.usenix.org/system/files/atc22-lion.pdf
  • [技术干货] 【CANN训练营】【2022第二季】【进阶班】 hw37497260 --animeGAN_picture样例c++实现
    1. 购买ECS云服务器2. 通过MobaXterm访问购买的云服务器3. 切换到HwHiAiUser用户4. 获取源码:命令行运行:git clone https://gitee.com/ascend/samples.git 可以看到目录中有samples文件夹5. 进行模型下载并转换(1)进入samples/cplusplus/level2_simple_inference/6_other/animeGAN_picture/model目录(2)下载三种shape的模型256*256:wget https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/animeGAN_picture/AnimeGAN_256_256.pbwget https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/animeGAN_picture/aipp_256_256.cfg512*512:wget https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/animeGAN_picture/AnimeGAN_512_512.pbwget https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/animeGAN_picture/aipp_512_512.cfg 1024*1024:wget https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/animeGAN_picture/AnimeGAN_1024_1024.pbwget https://c7xcode.obs.cn-north-4.myhuaweicloud.com/models/animeGAN_picture/aipp_1024_1024.cfg (3)模型转换atc --model="./AnimeGAN_256_256.pb" --output_type=FP32 --input_shape="test:1,256,256,3" --input_format=NHWC --output="AnimeGANv2_256" --soc_version=Ascend310 --framework=3 --precision_mode=allow_fp32_to_fp16 --insert_op_conf=aipp_256_256.cfgatc --model="./AnimeGAN_512_512.pb" --output_type=FP32 --input_shape="test:1,512,512,3" --input_format=NHWC --output="AnimeGANv2_512" --soc_version=Ascend310 --framework=3 --precision_mode=allow_fp32_to_fp16 --insert_op_conf=aipp_512_512.cfgatc --model="./AnimeGAN_1024_1024.pb" --output_type=FP32 --input_shape="test:1,1024,1024,3" --input_format=NHWC --output="AnimeGANv2_1024" --soc_version=Ascend310 --framework=3 --precision_mode=allow_fp32_to_fp16 --insert_op_conf=aipp_1024_1024.cfg6. 样例部署, 执行编译脚本,进行样例编译进入/animeGAN_picture/scripts目录,运行samples_build.sh,同时测试图片mountain.jpg已下载到/animeGAN_picture/data目录下原图如下:7.样例运行进入/animeGAN_picture/scripts目录,运行samples_run.sh,需要输入shape大小,即 bash sample_run.sh 256。输出的图片在/animeGAN_picture/out/output目录下输出效果如下:
  • [分享交流] C++工程师视角下的Rust,有何不同?
    如果说C++在内存安全上做出了自己的努力,那么在线程并发安全上则努力程度还不够;而Rust则是从一开始就在内存安全和线程安全上下足了功夫,同时没有抛弃性能。在一些基本的语言表达方式上,Rust和C/C++存在一些不同,体现在:(1)变量默认是不可变绑定(let),需要修改变量,则需明确使用可变绑定(let mut);(2)没有实现Copy trait的对象,绑定、赋值、非引用传参时默认是移动语义;(3)支持函数内嵌定义;(4)支持函数表达式返回(最后不加分号);(5)在同一个作用域内,变量可以重新绑定(let),在Rust中叫做遮蔽机制;(6)支持零尺寸的结构体、空枚举、空数组([T, 0]);(7)两种字符串类型变量:&str相当于C++中的const char*,用于指向字符串字面常量;而String相对于C++中的std::string,支持可变引用&Mut String和不可变引用&String;(8)基本的数据类型都实现了Copy trait,默认在栈上分配,支持复制语义;而String、Vec等默认只支持移动语义,要进行深拷贝,需要显式调用clone函数;(9)不支持switch & case,使用match模式匹配代替;(10)不支持三目运算符;(11)支持?运算符,用于调用的函数返回异常时,直接退出当前函数并返回对应的错误Err<T>;……
  • [技术干货] C++常见面试题总结[转载]
    1、C和C++的区别1)C是面向过程的语言,是一个结构化的语言,考虑如何通过一个过程对输入进行处理得到输出;C++是面向对象的语言,主要特征是“封装、继承和多态”。封装隐藏了实现细节,使得代码模块化;派生类可以继承父类的数据和方法,扩展了已经存在的模块,实现了代码重用;多态则是“一个接口,多种实现”,通过派生类重写父类的虚函数,实现了接口的重用。2)C和C++动态管理内存的方法不一样,C是使用malloc/free,而C++除此之外还有new/delete关键字。3)C++中有引用,C中不存在引用的概念2、C++中指针和引用的区别1)指针是一个新的变量,存储了另一个变量的地址,我们可以通过访问这个地址来修改另一个变量;引用只是一个别名,还是变量本身,对引用的任何操作就是对变量本身进行操作,以达到修改变量的目的2)引用只有一级,而指针可以有多级3)指针传参的时候,还是值传递,指针本身的值不可以修改,需要通过解引用才能对指向的对象进行操作引用传参的时候,传进来的就是变量本身,因此变量可以被修改3、结构体struct和共同体union(联合)的区别结构体:将不同类型的数据组合成一个整体,是自定义类型共同体:不同类型的几个变量共同占用一段内存1)结构体中的每个成员都有自己独立的地址,它们是同时存在的;共同体中的所有成员占用同一段内存,它们不能同时存在;2)sizeof(struct)是内存对齐后所有成员长度的总和,sizeof(union)是内存对齐后最长数据成员的长度、结构体为什么要内存对齐呢?1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常2.硬件原因:经过内存对齐之后,CPU的内存访问速度大大提升。4、#define和const的区别1)#define定义的常量没有类型,所给出的是一个立即数;const定义的常量有类型名字,存放在静态区域2)处理阶段不同,#define定义的宏变量在预处理时进行替换,可能有多个拷贝,const所定义的变量在编译时确定其值,只有一个拷贝。3)#define定义的常量是不可以用指针去指向,const定义的常量可以用指针去指向该常量的地址4)#define可以定义简单的函数,const不可以定义函数5、重载overload,覆盖(重写)override,隐藏(重定义)overwrite,这三者之间的区别1)overload,将语义相近的几个函数用同一个名字表示,但是参数列表(参数的类型,个数,顺序不同)不同,这就是函数重载,返回值类型可以不同特征:相同范围(同一个类中)、函数名字相同、参数不同、virtual关键字可有可无2)override,派生类覆盖基类的虚函数,实现接口的重用,返回值类型必须相同特征:不同范围(基类和派生类)、函数名字相同、参数相同、基类中必须有virtual关键字(必须是虚函数)3)overwrite,派生类屏蔽了其同名的基类函数,返回值类型可以不同特征:不同范围(基类和派生类)、函数名字相同、参数不同或者参数相同且无virtual关键字6、new、delete、malloc、free之间的关系new/delete,malloc/free都是动态分配内存的方式1)malloc对开辟的空间大小严格指定,而new只需要对象名2)new为对象分配空间时,调用对象的构造函数,delete调用对象的析构函数既然有了malloc/free,C++中为什么还需要new/delete呢?运算符是语言自身的特性,有固定的语义,编译器知道意味着什么,由编译器解释语义,生成相应的代码。库函数是依赖于库的,一定程度上独立于语言的。编译器不关心库函数的作用,只保证编译,调用函数参数和返回值符合语法,生成call函数的代码。malloc/free是库函数,new/delete是C++运算符。对于非内部数据类型而言,光用malloc/free无法满足动态对象都要求。new/delete是运算符,编译器保证调用构造和析构函数对对象进行初始化/析构。但是库函数malloc/free是库函数,不会执行构造/析构。7、delete和delete[]的区别delete只会调用一次析构函数,而delete[]会调用每个成员的析构函数用new分配的内存用delete释放,用new[]分配的内存用delete[]释放一.构造函数构造函数是和类名相同的一个函数,它的作用是实现对象的初始化。当对象被创建时,构造函数自动被调用。特点:没有类型没有返回值(也不用写void)名字与类名相同可重载!作用:完成类的对象的初始化Cdate d; //定义对象d注意:当对象d被创建时,会自动调用构造函数 d.Cdate()。当类中未定义构造函数时,编译器会自动假设存在以下两个默认构造函数:(此构造函数什么都不做,就是个形式)。如果作者自己定义了构造函数,则默认的构造函数不会存在。//默认构造函数一 Cdate::Cdate() { } //默认构造函数二 Cdate::Cdate(const Cdate& a) { }三.析构函数我们已经知道构造函数是在创建对象时,对其进行初始化。而析构函数与其相反,是在对象被删除前象由系统自动执行它做清理工作。作为一个类,可能有多个对象,每个对象生命结束时都要调用析构函数,且每个对象调用一次。特点:无类型无返回值名字与类名相同不带参数,不可重载,析构函数只有一个!析构函数前“~” (取反符,表示逆构造函数)作用:在对象被删除前做清理工作。注意:对象的析构函数在对象被销毁前被调用,对象何时销毁也与其作用域相关。例如,全局对象是在程序运行结束时销毁;自动对象是在离开其作用域时销毁;而动态对象是在使用delete运算符时销毁。析构函数特别适用于当一个对象被动态分配内存空间,而在对象被销毁前希望释放它所占用的内存空间的时候。我们不会忽略初始化的重要性,却常常忽略清除的重要性,然而对销毁变量的内存清理是非常重要的。例如,我们在堆中申请了一些内存,如果没有用完就释放,会造成内存泄露,会导致应用程序运行效率降低,甚至崩溃,不可掉以轻心。而在c++中提供有析构函数,可以保证对象清除工作自动执行。析构与构造的调用次序相反,即最先构造的最后被析构,最后构造的最先被析构。7.1、虚函数、纯虚函数虚函数:虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数,是C++中多态性的一个重要体现。利用基类指针访问派生类中的虚函数,这种情况下采用的是动态绑定技术。纯虚函数:纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”.纯虚函数不能实例化对象。抽象类的介绍抽象类是一种特殊的类,它是为了抽象和设计的目的为建立的,它处于继承层次结构的较上层。(1)抽象类的定义: 称带有纯虚函数的类为抽象类。(2)抽象类的作用: 抽象类的主要作用是将有关的操作作为结果接口组织在一个继承层次结构中,由它来为派生类提供一个公共的根,派生类将具体实现在其基类中作为接口的操作。所以派生类实际上刻画了一组子类的操作接口的通用语义,这些语义也传给子类,子类可以具体实现这些语义,也可以再将这些语义传给自己的子类。(3)使用抽象类时注意:抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类中没有重新定义纯虚函数,而只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体的类。抽象类是不能定义对象的。总结:1、纯虚函数声明如下: virtual void funtion1()=0; 纯虚函数一定没有定义,纯虚函数用来规范派生类的行为,即接口。包含纯虚函数的类是抽象类,抽象类不能定义实例,但可以声明指向实现该抽象类的具体类的指针或引用。2、虚函数声明如下:virtual ReturnType FunctionName(Parameter) 虚函数必须实现,如果不实现,编译器将报错,错误提示为:3、对于虚函数来说,父类和子类都有各自的版本。由多态方式调用的时候动态绑定。4、实现了纯虚函数的子类,该纯虚函数在子类中就编程了虚函数,子类的子类即孙子类可以覆盖该虚函数,由多态方式调用的时候动态绑定。5、虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数。6、在有动态分配堆上内存的时候,析构函数必须是虚函数,但没有必要是纯虚的。纯虚函数的引入,是出于两个目的:1、为了安全,因为避免任何需要明确但是因为不小心而导致的未知的结果,提醒子类去做应做的实现。2、为了效率,不是程序执行的效率,而是为了编码的效率。动态绑定:基类指针是调用派生类的中的成员函数还是调用基类中的成员函数要到程序运行时确定。主要看此时基类指针所指向的对象。 这里要涉及一些很重要的概念,也是我最近看完Effective C++才明白的东西,记录下来。这些概念就是静态类型和动态类型,静态绑定和动态绑定。静态绑定和动态绑定。静态绑定是说前期绑定。 所谓对象的静态类型,就是它在程序中被声明的时候采用的类型。 考虑下面的class继承体系:class Shape{ virtual void draw(color = Red) const=0; ... ... }; class Rectangle:public Shape{ virtual void draw(color = Red) const; ... ... }; class Circle:public Shape { virtual void draw(color = Red) const;   ... ... }; 现在考虑以下这些指针: Shape* ps;//静态类型为Shape* Shape*pc =new Circle;//静态类型Shape* Shape*pr = new Rectangle;//静态类型Shape*在本例中,ps,pc,pr都被声明为Shape*类型的,所以它们的静态类型都是Shape*。注意:无论它们真正指向什么,它们的静态类型都是Shape*. 所谓的对象的动态类型是指“当前所指对象的类型”。也就是说,动态类型可以表现出一个对象将会有什么行为。根据上面的例子,pc的动态类型是Circle*,pr的动态类型是Rectangle*。ps没有动态类型,因为它没有指向任何对象。 动态类型一如其名所示,可以在执行过程中改变(通常是经过赋值运算):ps=pc; \\ps的动态类型如今是Circle* ps=pr; \\ps的动态类型如今是Rectangle*Virtual函数系动态绑定而来,意思是调用一个virtual函数的时候,究竟调用的是哪一个函数代码,取决于发出调用的那个对象的动态类型。ps->draw(); \\调用的是Rectangle::draw(Red)8、STL库用过吗?常见的STL容器有哪些?算法用过几个?STL包括两部分内容:容器和算法容器即存放数据的地方,比如array, vector,分为两类,序列式容器和关联式容器序列式容器,其中的元素不一定有序,但是都可以被排序,比如vector,list,queue,stack,heap, priority-queue, slist关联式容器,内部结构是一个平衡二叉树,每个元素都有一个键值和一个实值,比如map, set, hashtable, hash_set算法有排序,复制等,以及各个容器特定的算法迭代器是STL的精髓,迭代器提供了一种方法,使得它能够按照顺序访问某个容器所含的各个元素,但无需暴露该容器的内部结构,它将容器和算法分开,让二者独立设计。Vector是顺序容器,是一个动态数组,支持随机存取、插入、删除、查找等操作,在内存中是一块连续的空间。在原有空间不够情况下自动分配空间,增加为原来的两倍。vector随机存取效率高,但是在vector插入元素,需要移动的数目多,效率低下。注意:vector动态增加大小时,并不是在原空间之后持续新空间(因为无法保证原空间之后尚有可供配置的空间),而是以原大小的两倍另外配置一块较大的空间,然后将原内容拷贝过来,然后才开始在原内容之后构造新元素,并释放原空间。因此,对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了。————————————————版权声明:本文为CSDN博主「Cpp编程小茶馆」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/xu_fu_yong/article/details/122948379
  • [应用开发] 【C++应用开发】acl 或者mindx c++ yolov5 v5.0以上支持样例 是否更新
    有看到mindx sdk支持到v5.0,modelzoo提供了python样例,请问c++样例有无能支持到v6.0,使用自训练模型,并使用了autoanhor,mindx样例model的yolov5.cfg里的bias是否要修改
  • [其他问题] 【众智】【计算算子】报错 The uator of the primitive is not defined
    【功能模块】MindSpore的CPU计算算子。【操作步骤&问题现象】我正在学习开发一个简单的算子以理解编译的全流程。我的尝试方法是实现一个叫做“eya”的算子,该算子除了名称以外与eye算子(其功能为创建单位矩阵)完全一致。我在算子前端、C++侧推导、底层实现等CPU开发涉及文件都仿照eye算子做了添加和修改(即,在算子开发涉及文件中,先将eye算子部分的代码完全复制一份,然后仅将“eye”名称替换为“eya”),并在编译后能顺利在python中导入该算子。但是在执行时出现了RuntimeError报错并提示“The evaluator of the primitive is not defined”。在尝试解决该报错的过程中,我还参阅了在网上能找到的所有相关issue的讨论如下,但未能为求解提供帮助:参考issue1:https://bbs.huaweicloud.com/forum/thread-136641-1-1.html结果:已检查“mindspore/core/core_ops.h”中对PrimitivePtr的定义,与原先eye算子的实现完全一致(见下面的【其它信息】说明),故未能提供帮助参考issue2:https://toscode.gitee.com/mindspore/mindspore/issues/I4NX69结果:由于该issue所参考的官网链接已404失效,且issue中没有交代具体求解方案,故未能提供帮助请问该问题所反映的出错程序可能会在哪个部分呢?或者为了解决该报错如何进行进一步调试呢?感谢。【截图信息】调试命令和返回报错结果如下:【其它信息】修改C++侧推导文件时,在\mindspore\core\ops\core_ops.h中插入的代码为(与eye算子除了名称以外其他完全一致):constexpr auto kEya = "Eya";GVAR_DEF(PrimitivePtr, kPrimEya, std::make_shared<Primitive>(kEya));其它如算子前端、底层实现等文件,同样是除了名称以外其他代码与eye算子完全一致。
  • [MindX SDK] 运行C++ run.sh脚本报错
    运行run.sh脚本提示如下错误,这个是我哪一步没有执行呀,同时有没有运行C++示例的说明呀
  • [问题求助] 运行atlas200dk上的/mxVision/C++ 报错
    atlas200dk 运行/mxVision/C++,报错,不知道如何排查,日志如下【日志信息】(可选,上传日志内容或者附件)
  • [问题求助] 【Atlas 200 DK】【Mindstudio】关于Mindstudio运行c++程序的几点疑惑
    如果需要使用Mindstudio运行c++程序,正确的操作步骤是什么?以下步骤是否正确?1)在虚拟机端启动Mindstudio软件,远程登陆开发板;2)在虚拟机用户中以分设方式(虚拟机为开发环境,开发板为运行环境)配置开发环境,并安装C++所需第三方依赖;3)Mindstudio中编译、运行程序。如若以上操作步骤正确,请问还有其他使用Mindstudio运行c++程序的方式吗?如若以上操作步骤不正确,请问正确使用Mindstudio运行c++程序的方式是什么?
  • [应用开发] 【MDC300】【AI推理】在部署时是选python还是c++
    【功能模块】深度学习模型部署【操作步骤&问题现象】1、深度学习模型(如检测、跟踪)部署时,是选用c++还是培养python?mdc300 mini上能否pip安装?python是否支持和c++程序之间的通信?2、modelzoo给的模型大部分是基于python的,是否能支持转换为om模型?算子是否支持?
  • [数据处理] 【MindSpore】【C++拓展功能】MindSpore是否支持使用C++编译扩展模块?
    【功能模块】 C++拓展 【操作步骤&问题现象】 模型开发过程中遇到需要自定义Tensor运算逻辑的情况。Pytorch可以通过torch.utils.cpp_extension扩展C++代码,请问mindspore是否有类似功能支持?
总条数:237 到第
上滑加载中