代码疑云

代码疑云(1)-掌握初始化列表


代码

  1. #include<iostream>
  2. usingnamespacestd;
  3. classA
  4. {
  5. private:
  6. intx1;
  7. intx2;
  8. public:
  9. A():x2(1),x1(x2++){}//初始化列表
  10. voidprint()
  11. {
  12. cout<<"x1="<<x1<<endl
  13. <<"x2="<<x2<<endl;
  14. }
  15. };
  16. intmain()
  17. {
  18. Aa;
  19. a.print();
  20. return0;
  21. }

:x1,x2最终被输出什么值呢?为什么?

解答:上机调试下会发现输出的结果是:x1是一个随机数,x2是1。为什么?因为在初始化列表中在给x1赋值为x2++时,这个x2并未初始化,也就是说x2里面什么东西也没装。也许你会问我不是在前面已经给x2赋值了吗,没错,但是有一个问题你忽略了,那就是初始化列表的赋值顺序是依照x1和x2的声明顺序的顺序来初始化的,也就是说在代码中,程序是先给x1赋值为x2++(此时x2并未初始化),再给x2赋值为1。还有初始化列表里的赋值,是在变量被声明时进行的,所以多使用初始化列表是可以提升程序效率的。

!!代码疑云系列由本人在天天唯C论坛下首发


代码疑云(2)-c函数调用约定

代码:

  1. #include<iostream>
  2. usingnamespacestd;
  3. voidfoo(intp1,intp2,intp3)
  4. {
  5. cout<<"p1="<<p1<<endl
  6. <<"p2="<<p2<<endl
  7. <<"p3="<<p3<<endl;
  8. }
  9. intmain()
  10. {
  11. inti;
  12. cout<<"firstcall:"<<endl;
  13. i=0;
  14. foo(++i,++i,++i);
  15. cout<<"secondcall:"<<endl;
  16. i=0;
  17. foo(++i,i++,i++);
  18. return0;
  19. }

:两次调用foo函数分别输出了什么,为什么?

解答:按照cedel函数调用的约定,编译器使参数从左到右的入栈。第一次调用为什么p1,p2,p3的值全是3呢,原因在此,在foo被call之前三++i 操作将先被操作也就是连续自增了3次,最终结果i 的值是3,然后是编译器push(i),push(i),push(i)三次入栈,然后call到foo定义处依次出栈并相应地复制给了形参。第二次调用foo时,一开始与第一次一样先是计算三次++操作,但是所不同的是最后两个是i++,i++ 刚没说到它们的计算顺序,编译器计算这些的顺序是由右到左的,也就是先i++,再i++,最后是++i,而运算i++是先取值再自增的,编译器会先把i (这时为0)存入寄存器(cpu中的存储器),再加1,然后计算下一个i++ 与前一次一样,所不同的是这次 i 的值是1,因为前面已加1 ,最后++i 。

!!代码疑云系列由本人在天天唯C论坛下首发



代码疑云(3)-静态字符串

代码:

  1. #include<iostream>
  2. usingnamespacestd;
  3. intmain()
  4. {
  5. char*str1="string";
  6. char*str2="string";
  7. if(str1==str2)
  8. cout<<"str1issameasstr2";
  9. }

:str1 的值是否等于 str2 而输出字符串“str1 is same as str2”呢,为什么? 解答:是的 “str1 is same as srr2”,也就是说str1与str2指向了相同的内存地址,因为"string"是静态对象,是由编译器分配给他的内存空间,在代码中出现了两次,编译器并不会给他们分别分配空间,因为如果这样将会造成不必要的浪费。


代码疑云(4)-类的sizeof值

代码:

  1. #include<iostream>
  2. usingnamespacestd;
  3. classA
  4. {
  5. };
  6. classB
  7. {
  8. chara;
  9. intb;
  10. };
  11. classC
  12. {
  13. voidfoo(){};
  14. };
  15. classD
  16. {
  17. virtualvoidfoo(){};
  18. };
  19. intmain()
  20. {
  21. cout<<sizeof(A)<<sizeof(B)<<sizeof(C)<<sizeof(D);
  22. return0;
  23. }

:结果是什么,为什么呢?

解答:sizeof(A)为1,而不是0,虽然空类没有任何成员变量,但其实体提供取地址操作,所以其内存空间不能为0。sizeof(B)为8,编译器在计算类体或结构体变量的地址时是通过字节对齐的方式进行的,也就是通过加多少偏移量来确认是那个变量。类的偏移量为其最大内存空间的类型的成员变量的长度,其最大内存空间类型成员是int,所以偏移量为4字节,即char a成员需要补上3个字节,才能让编译器准确高效地寻址,再加上int的4字节,sizeof(B)就是8了。sizeof(C)为1,类的成员函数在编译器编译时,其函数地址就已自动存放,所以不必为其分配额外的空间来存放他,所以它的长度跟空类一样为1。sizeof(D)为4,因为类D需要构造一虚函数列表来存放函数指针以实现动态调用,一个指针的长度占用4个字节,所以为4.


代码疑云(5)-类成员函数的thiscall约定

代码:

  1. #include<iostream>
  2. usingnamespacestd;
  3. classA
  4. {
  5. private:
  6. intvalue;
  7. public:
  8. A()
  9. {
  10. value=0;
  11. }
  12. voidcoutHello()
  13. {
  14. cout<<"hello"<<endl;
  15. }
  16. voidcoutValue()
  17. {
  18. cout<<value<<endl;
  19. }
  20. };
  21. intmain()
  22. {
  23. A*pA=NULL;//空指针,所指向的内容不可访问存取
  24. pA->coutHello();
  25. pA->coutValue();
  26. return0;
  27. }

(感谢网友提供的题目)

疑:调用coutHello和coutValue方法有什么问题?
解答: 成员函数的地址在编译器编译时给出的,所以是已知的,根据thiscall约定,类的成员函数在编译时编译器会传入一个this指针,通过this指针指向成员变量,在调用couthello时并未用到this指针所以调用正常,而调用coutvalue时,value需要用到this指针,因为此时this是NULL指针,所以会发生内存报错。



代码疑云(6)-头文件的正确定义

代码:

头文件print_tools.h

  1. #include<stdio.h>
  2. voidprintStr(constchar*pStr)
  3. {
  4. printf("%s\n",pStr);
  5. }
  6. voidprinttInt(constinti)
  7. {
  8. printf("%d\n",i);
  9. }

头文件counter.h
  1. #include"print_tools.h"
  2. staticintsg_value;
  3. voidcounter_init()
  4. {
  5. sg_value=0;
  6. }
  7. voidcounter_count()
  8. {
  9. sg_value++;
  10. }
  11. voidcounter_out_result()
  12. {
  13. printStr("theresultis:");
  14. printtInt(sg_value);
  15. }

main.cpp
  1. #include"print_tools.h"
  2. #include"counter.h"
  3. intmain()
  4. {
  5. charch;
  6. counter_init();
  7. printStr("pleaseinputsomecharactors:");
  8. while((ch=getchar())!='$')
  9. {
  10. if(ch=='A')
  11. <spanstyle="white-space:pre"></span>counter_count();
  12. }
  13. counter_out_result();
  14. }

疑:以上代码编译时有何问题吗,是什么导致的呢?

解答:void printStr(const char*)和'void printtInt(int) 函数redefine了,道理很简单,因为在counter.h中已包含了print_tools.h,在main.cpp中又包含了print_tools.h头文件,也就是两次包含了print_toosl.h,所以也就发生了重定义错误,这是初学者常见问题,要避免这个问题,我们必须采取防范措施,就是使用预编译命令,如下作修改:

头文件print_tools.h

  1. #ifndefPRINT_TOOLS_H//如果未定义PRINT_TOOLS_H
  2. #definePRINT_TOOLS_H//则定义然后编译以下源代码
  3. #include<stdio.h>
  4. voidprintStr(constchar*pStr)
  5. {
  6. printf("%s\n",pStr);
  7. }
  8. voidprinttInt(constinti)
  9. {
  10. printf("%d\n",i);
  11. }
  12. #endif//结束//如此改头文件就只被编译器编译一次了,起到了防范重定义错误的作用

头文件counter.h
  1. #ifndefCOUNTER_H//
  2. #defineCOUNTER_H//
  3. #include"print_tools.h"
  4. staticintsg_value;
  5. voidcounter_init()
  6. {
  7. sg_value=0;
  8. }
  9. voidcounter_count()
  10. {
  11. sg_value++;
  12. }
  13. voidcounter_out_result()
  14. {
  15. printStr("theresultis:");
  16. printtInt(sg_value);
  17. }
  18. #endif//

在一个工程项目中头文件众多繁杂,采用这个方法可以很好的避免,所以每当我们定义一个头文件时要养成如此的良好习惯。


代码疑云(7)-构造函数在类继承时

代码

  1. #include<iostream>
  2. usingnamespacestd;
  3. classA
  4. {
  5. public:
  6. A()
  7. {
  8. Print();
  9. }
  10. virtualvoidPrint()
  11. {
  12. cout<<"Aisconstructed.\n";
  13. }
  14. };
  15. classB:publicA
  16. {
  17. public:
  18. B()
  19. {
  20. Print();
  21. }
  22. virtualvoidPrint()
  23. {
  24. cout<<"Bisconstructed.\n";
  25. }
  26. };
  27. intmain()
  28. {
  29. A*pA=newB();
  30. deletepA;
  31. return0;
  32. }
(感谢网友提供的题目)

以上代码输出结果是?

输出结果如下:
A is constructed.
B is constructed.
解释:当new B()时,因为B继承了A,所以编译器首先调用A的构造函数,A的构造函数里是调用A类里的Print(),所以首先输出A is constructed ,然后调用的是B的构造函数,此时Print虚函数指针已指向B的void print(),所以输出B is constructed。





本项目采用C++编程语言结合ROS框架构建了完整的双机械臂控制系统,实现了Gazebo仿真环境下的协同运动模拟,并完成了两台实体UR10工业机器人的联动控制。该毕业设计在答辩环节获得98分的优异成绩,所有程序代码均通过系统性调试验证,保证可直接部署运行。 系统架构包含三个核心模块:基于ROS通信架构的双臂协调控制器、Gazebo物理引擎下的动力学仿真环境、以及真实UR10机器人的硬件接口层。在仿真验证阶段,开发了双臂碰撞检测算法和轨迹规划模块,通过ROS控制包实现了末端执行器的同步轨迹跟踪。硬件集成方面,建立了基于TCP/IP协议的实时通信链路,解决了双机数据同步和运动指令分发等关键技术问题。 本资源适用于自动化、机械电子、人工智能等专业方向的课程实践,可作为高年级课程设计、毕业课题的重要参考案例。系统采用模块化设计理念,控制核心与硬件接口分离架构便于功能扩展,具备工程实践能力的学习者可在现有框架基础上进行二次开发,例如集成视觉感知模块或优化运动规划算法。 项目文档详细记录了环境配置流程、参数调试方法和实验验证数据,特别说明了双机协同作业时的时序同步解决方案。所有功能模块均提供完整的API接口说明,便于使用者快速理解系统架构并进行定制化修改。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
【微电网】【创新点】基于非支配排序的蜣螂优化算法NSDBO求解微电网多目标优化调度研究(Matlab代码实现)内容概要:本文围绕基于非支配排序的蜣螂优化算法(NSDBO)在微电网多目标优化调度中的应用展开研究,提出了一种改进的智能优化算法以解决微电网系统中经济性、环保性和能源效率等多重目标之间的权衡问题。通过引入非支配排序机制,NSDBO能够有效处理多目标优化中的帕累托前沿搜索,提升解的多样性和收敛性,并结合Matlab代码实现仿真验证,展示了该算法在微电网调度中的优越性能和实际可行性。研究涵盖了微电网典型结构建模、目标函数构建及约束条件处理,实现了对风、光、储能及传统机组的协同优化调度。; 适合人群:具备一定电力系统基础知识和Matlab编程能力的研究生、科研人员及从事微电网、智能优化算法应用的工程技术人员;熟悉优化算法与能源系统调度的高年级本科生亦可参考。; 使用场景及目标:①应用于微电网多目标优化调度问题的研究与仿真,如成本最小化、碳排放最低与供电可靠性最高之间的平衡;②为新型智能优化算法(如蜣螂优化算法及其改进版本)的设计与验证提供实践案例,推动其在能源系统中的推广应用;③服务于学术论文复现、课题研究或毕业设计中的算法对比与性能测试。; 阅读建议:建议读者结合文中提供的Matlab代码进行实践操作,重点关注NSDBO算法的核心实现步骤与微电网模型的构建逻辑,同时可对比其他多目标算法(如NSGA-II、MOPSO)以深入理解其优势与局限,进一步开展算法改进或应用场景拓展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值