本文共 3762 字,大约阅读时间需要 12 分钟。
对于类的常成员函数的描述正确的是()
A.常成员函数不修改类的数据成员
B.常成员函数可以对类的数据成员进行修改 C.常成员函数只能由常对象调用 D.常成员函数不能访问类的数据成员答案:A
常成员函数含义是通过该函数只能读取同一类中的数据成员的值,而不能修改它。
常对象只能调用常函数成员,不能调用非const 函数成员问题。
C/C++的编译包括几个部分?
答案:编译、汇编、链接
具体的包括:预处理、编译、汇编、链接
1、预编译:预处理器对c程序进行一些预处理工作,例如对宏定义的变量进行替换;
1)将所有的#define删除,并展开所有的宏定义;
2)处理所有的预编译指令,例如:#if,#elif,#else,#endif;
3)处理#include预编译指令,将被包含的文件插入到预编译指令的位置;
4)添加行号信息文件名信息,便于调试;
5)删除所有的注释:// /**/;
6)保留所有的#pragma编译指令,因为在编写程序的时候,我们经常要用到#pragma指令来设定编译器的状态或者是指示编译器完成一些特定的动作;
最后生成.i文件;
总的来说,包括(1)去注释 (2)宏替换 (3)头文件展开 (4)条件编译
2、编译:编译器将c语言程序翻译成汇编语言程序;
1)扫描,语法分析,语义分析,源代码优化,目标代码生成,目标代码优化;
2)生成汇编代码;
3)汇总符号;
4)生成.s文件;
3、汇编:汇编语言通过汇编器编译成可重定位目标程序.o,与之相反称为反汇编;
1)根据汇编指令和特定平台,把汇编指令翻译成二进制形式;
2)合并各个section,合并符号表;
3)生成.o文件;
4、链接:将目标文件和所需的库函数用链接器进行链接,常见的链接器有Unix;
1)合并各个.obj文件的section,合并符 号表,进行符号解析;
2)符号地址重定位;
3)生成可执行文件;
typedef union { Short i; int k[5]; char c;} Mat;Typedef struct { int i; Mat j; double k;}Like;
则语句 printf("%d",sizeof(Like)+sizeof(Mat));的执行结果是?
答案:32Mat里面最大元素是int k[5]
占20Byte,所以Mat的大小就是20Byte。
注意!!!Mat的长度大小是20Byte,并不是说Mat是一个以20Byte为单位的新数据,而是在内存中开辟了一段大小为20Byte的空间,至于空间中的数据类型是什么,是不确定的。Union只要保证连续的空间是最大的范围就行
其实struct与union一样,都是申请一段连续的内存空间,只不过struct更注重内存对齐。
所以在Like中,最大的成员是double k
应该以8Byte对齐,也就是Like的大小是8的整数。然而在内存分配的时候Mat是作一个20Byte的空间,而且可以使用这20Byte的空间进行struct的内存对齐的。
所以在Link中,以8Byte对齐,int i
占4Byte,从union中接着放4Byte来对齐8Byte,union中还剩下16Byte正好对齐,接着double k
8Byte对齐,所以总的大小就是8+16+8=32Byte。
所以当union变换时:
typedef union { short i; int k[3]; char c; float f; //即使有float也不影响下面struct对齐的时候,给int i借4Byte} Mat;typedef struct { int i; Mat j; double k;}Like;sizeof(Like) = 24
根据上面所说,union只是一个12Byte的空间,可以在struct中被用来填充内存对齐,所以在struct中int i
4Byte向union借了4Byte用来对齐8Byte,union剩下8Byte正好对齐,double k正好对齐,所以总的大小就是8+8+8=24。
union 写得好的博客:https://blog.csdn.net/huqinweI987/article/details/23597091?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control
三点:
力扣:https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/
遍历数组,判断数组是否在哈希表中。
由于此数组的大小为n,数组元素的范围也是0~n-1,所以没有重复的情况下应该是下标i对应的位置元素就是i。
所以,我们可以遍历数组,在遍历中不断纠正数组元素与下标的位置关系!!!这就是原地置换,核心思想就是不断纠正下标与元素的对应关系。
当下标与元素不对应的时候,就要纠正了,将元素对元素对应下标上的元素互换位置(我们默认唯一下标对应唯一元素的),交换后再次判断下标与元素的关系,就这样一直判断。
但是实际上我们知道是有重复元素的,也就是重复元素会占用其他元素的下标,我们上面交换的过程就是验证对应下标上的元素是不是当前要判断的元素,如果是!说明当前元素在那个下标上重复了。
在当前下标的基础上纠正,如果找到对应的元素,那就纠正下一个,如果在纠正的过程中遇到了重复的元素,那就退出。
第一版代码:
int findRepeatNumber(int* nums, int numsSize){ int i, k; for (i = 0; i < numsSize; ++i) { while (nums[i] != i) { //一直纠正 if (nums[i] == nums[nums[i]]) { //找到重复 return nums[i]; } /* 不重复且位置错误 纠正 */ k = nums[i]; nums[i] = nums[nums[i]]; nums[nums[i]] = k; } } return -1;}
但是一直提示超出时间限制
使用C++提交后就ok:
class Solution { public: int findRepeatNumber(vector & nums) { int k; for (int i = 0; i < nums.size(); ++i) { while (nums[i] != i) { //纠正开始 if (nums[i] == nums[nums[i]]) { //判断重复 return nums[i]; } swap(nums[i], nums[nums[i]]); //交换纠正 } } return -1; }};
因为是最多一次遍历就可以得出,所以时间复杂度是O(n),另外所有的操作都是基于原数组的,所以空间复杂度为O(1)。
长度为 n;元素范围0~n-1;只要求出任意重复元素
,这些都是在提示规律,和数组的长度、下标、随机存取特性有关