招商网站建设的必要性,什么网站专门做自由行的,温州网站建设wmwl,蒙古文网站建设工作计划点击蓝字关注我们11、extern 用法#xff1f;extern 修饰变量的声明如果文件a.c 需要引用b.c 中变量int v#xff0c;就可以在a.c 中声明extern int v#xff0c;然后就可以引用变量v。extern 修饰函数的声明如果文件a.c 需要引用b.c 中的函数#xff0c;比如在b.c 中原型是… 点击蓝字关注我们11、extern 用法extern 修饰变量的声明如果文件a.c 需要引用b.c 中变量int v就可以在a.c 中声明extern int v然后就可以引用变量v。extern 修饰函数的声明如果文件a.c 需要引用b.c 中的函数比如在b.c 中原型是int fun(int mu)那么就可以在a.c 中声明extern int fun(int mu)然后就能使用fun 来做任何事情。就像变量的声明一样extern int fun(int mu)可以放在a.c 中任何地方而不一定非要放在a.c 的文件作用域的范围中。默认情况情况下函数都是extern的, 除非使用static对函数进行了隐匿extern 修饰符可用于指示C 或者C函数的调用规范。比如在C中调用C 库函数就需要在C程序中用extern “C”声明要引用的函数。这是给链接器用的告诉链接器在链接的时候用C 函数规范来链接。主要原因是C和C 程序编译完成后在目标代码中命名规则不同。12、int 转字符串, 字符串转intC11 标准增加了全局函数std::to_string可以使用std::stoi/std::stol/std::stoll 等等函数12.1 strcat,strcpy,strncpy,memset,memcpy 的内部实现strcat: char *strcat(char *dst, char const *src);首先找到dst的end以src的作为结束标志, 将src添加到dst的end上dst必须有足够的空间保存整个字符串dst和src都必须是一个由结尾的字符串(空字符串也行)dst和src内存不能发生重叠头文件: #include作用: 将dst和src字符串拼接起来保存在dst上注意事项:函数实现:Codechar *strcat (char * dst, const char * src){assert(NULL ! dst NULL ! src); // 源码里没有断言检测char * cp dst;while(*cp )cp; /* find end of dst */while(*cp *src) ; /* Copy src to end of dst */return( dst ); /* return dst */}strcpy: char *strcpy(char *dst, const char *src);src必须有结束符(), 结束符也会被复制src和dst不能有内存重叠dst必须有足够的内存头文件:#include作用: 将src的字符串复制到dst字符串内注意事项:函数实现:char *strcpy(char *dst, const char *src){ // 实现src到dst的复制if(dst src) return dst; //源码中没有此项assert((dst ! NULL) (src ! NULL)); //源码没有此项检查判断参数src和dst的有效性char *cp dst; //保存目标字符串的首地址while (*cp *src); //把src字符串的内容复制到dst下return dst;}strncpy: char *strncpy(char *dst, char const *src, size_t len);strncpy 把源字符串的字符复制到目标数组它总是正好向 dst 写入 len 个字符。如果 strlen(src) 的值小于 lendst 数组就用额外的 NULL 字节填充到 len 长度。如果 strlen(src)的值大于或等于 len那么只有 len 个字符被复制到dst中。这里需要注意它的结果将不会以NULL字节结尾。头文件: #include作用: 从src中复制len个字符到dst中, 如果不足len则用NULL填充, 如果src超过len, 则dst将不会以NULL结尾注意事项:函数实现:char *strncpy(char *dst, const char *src, size_t len){assert(dst ! NULL src ! NULL); //源码没有此项char *cp dst;while (len-- 0 *src ! \0)*cp *src;*cp \0; //源码没有此项return dst;}memset: void *memset(void *a, int ch, size_t length);将参数a所指的内存区域前length个字节以参数ch填入然后返回指向a的指针。在编写程序的时候若需要将某一数组作初始化memset()会很方便。一定要保证a有这么多字节头文件: #include作用:函数实现:void *memset(void *a, int ch, size_t length){assert(a ! NULL); void *s a; while (length--) { *(char *)s (char) ch; s (char *)s 1; } return a; }memcpy从 src 所指的内存地址的起始位置开始拷贝n个字节的数据到 dest 所指的内存地址的起始位置。可以用这种方法复制任何类型的值如果src和dst以任何形式出现了重叠它的结果将是未定义的。头文件: #include作用:函数实现:void *memcpy(void *dst, const void *src, size_t length){assert((dst ! NULL) (src ! NULL));char *tempSrc (char *)src; //保存src首地址char *tempDst (char *)dst; //保存dst首地址while(length-- 0) //循环length次复制src的值到dst中*tempDst *tempSrc ;return dst;}strcpy 和 memcpy 的主要区别复制的内容不同: strcpy 只能复制字符串而 memcpy 可以复制任意内容例如字符数组、整型、结构体、类等。复制的方法不同: strcpy 不需要指定长度它遇到被复制字符的串结束符才结束所以容易溢出。memcpy 则是根据其第3个参数决定复制的长度遇到并不结束。用途不同: 通常在复制字符串时用 strcpy而需要复制其他类型数据时则一般用 memcpy参考: 各种C语言处理函数 strcatstrcpystrncpymemsetmemcpy 总结 - New World - CSDN博客13、深拷贝与浅拷贝浅复制:只是拷贝了基本类型的数据而引用类型数据复制后也是会发生引用我们把这种拷贝叫做“(浅复制)浅拷贝”换句话说浅复制仅仅是指向被复制的内存地址如果原地址中对象被改变了那么浅复制出来的对象也会相应改变。深复制: 在计算机中开辟了一块新的内存地址用于存放复制的对象。浅复制的问题:在某些状况下类内成员变量需要动态开辟堆内存如果实行位拷贝也就是把对象里的值完全复制给另一个对象如AB。这时如果B 中有一个成员变量指针已经申请了内存那A 中的那个成员变量也指向同一块内存。这就出现了问题当B把内存释放了(如析构)这时A 内的指针就是野指针了出现运行错误。14、C模板是什么底层怎么实现的编译器并不是把函数模板处理成能够处理任意类的函数编译器从函数模板通过具体类型产生不同的函数编译器会对函数模板进行两次编译在声明的地方对模板代码本身进行编译在调用的地方对参数替换后的代码进行编译。这是因为函数模板要被实例化后才能成为真正的函数在使用函数模板的源文件中包含函数模板的头文件如果该头文件中只有声明没有定义那编译器无法实例化该模板最终导致链接错误。模板可以重载返回值, 函数重载不行如果我们试图通过在头文件中定义函数模板, 在cpp文件中实现函数模板, 那么我们必须在在实现的那个cpp文件中手动实例化, 也就是使用你需要使用的参数替换模板, 从而使得编译器为你编译生成相应参数的模板函数.15、C 语言struct 和C struct 区别struct 在C语言中:是用户自定义数据类型(UDT)只能是一些变量的集合体, 成员不能为函数没有权限设置一个结构标记声明后在C中必须在结构标记前加上struct才能做结构类型名;struct 在C中:是抽象数据类型(ADT)支持成员函数的定义(能继承能实现多态)。增加了访问权限, 默认访问限定符为public(为了与C 兼容)class 中的默认访问限定符为private定义完成之后, 可以直接使用结构体名字作为结构类型名可以使用模板16、虚函数可以声明为inline吗?虚函数要求在运行时进行类型确定而内敛函数要求在编译期完成相关的函数替换, 所以不能虚函数用于实现运行时的多态或者称为晚绑定或动态绑定。内联函数用于提高效率, 对于程序中需要频繁使用和调用的小函数非常有用。它是在编译期间对调用内联函数的地方的代码替换成函数代码。17、类成员初始化方式构造函数的执行顺序为什么用成员初始化列表会快一些概念赋值初始化通过在函数体内进行赋值初始化列表初始化在冒号后使用初始化列表进行初始化。这两种方式的主要区别在于对于在函数体中初始化,是在所有的成员函数分配空间后才进行的。对于类对象类型成员变量, 则是先调用零参数构造函数, 如果零参数构造函数不存在编译器将会报错.列表初始化是给数据成员分配内存空间时就进行初始化,就是说分配一个数据成员只要冒号后有此数据成员的赋值表达式(此表达式必须是括号赋值表达式)。快的原因: 所以对于列表初始化: 只进行了一次初始化操作, 而赋值初始化则先进性了一次初始化,然后调用了一次复制构造函数.一个派生类构造函数的执行顺序如下虚基类的构造函数(多个虚拟基类则按照继承的顺序执行构造函数)。基类的构造函数(多个普通基类也按照继承的顺序执行构造函数)。类类型的成员对象的构造函数(按照初始化顺序)派生类自己的构造函数。18、成员列表初始化必须使用成员初始化的四种情况当初始化一个引用成员时当初始化一个常量成员时基类 无零参数构造函数时成员类 无零参数构造函数时成员初始化列表做了什么编译器在调用用户代码之前, 会按照类成员声明顺序一一初始化成员变量, 如果成员初始化类别中有初值,则使用初值构造成员函数.初始化顺序由类中的成员声明顺序决定的不是由初始化列表的顺序决定的19、构造函数为什么不能为虚函数析构函数为什么要虚函数构造函数为什么不能为虚函数?首先是没必要使用虚函数:由于使用间接调用(通过引用或则指针)导致类类型不可信, 而使用虚函数机制完成正确的函数调用.但是构造函数本身是为了初始化对象实例, 创建对象必须制定它的类型, 其类类型是明确的, 因此在编译期间即可确定调用函数入口地址因而没必要使用虚函数, 其调用在编译时由编译器已经确定.其次不能使用虚函数:虚函数的调用依赖于虚函数表, 虚函数表储存于静态储存区, 在存在虚函数的对象中都将插入一个指向虚函数表的指针,在对象中插入一个指向虚函数表的指针是由构造函数完成的, 也就是说在调用构造函数时并没有指向虚函数表的指针, 也就不能完成虚函数的调用.析构函数为什么要虚函数C中基类采用virtual 虚析构函数是为了防止内存泄漏。如果派生类中申请了内存空间并在其析构函数中对这些内存空间进行释放。假设基类中采用的是非虚析构函数当删除基类指针指向的派生类对象时就不会触发动态绑定因而只会调用基类的析构函数而不会调用派生类的析构函数。那么在这种情况下派生类中申请的空间就得不到释放从而产生内存泄漏。所以为了防止这种情况的发生C中基类的析构函数应采用virtual 虚析构函数。20、析构函数的作用如何起作用析构函数名与类名相同,只是在函数名前增加了取反符号~以区别于构造函数,其不带任何参数, 也没有返回值. 也不允许重载.析构函数与构造函数的作用相反, 当对象生命周期结束的时候,如对象所在函数被调用完毕时,析构函数负责结束对象的生命周期. 注意如果类对象中分配了堆内存一定要在析构函数中进行释放.和拷贝构造函数类似,如果用户未定义析构函数, 编译器并不是一定会自动合成析构函数, 只有在成员变量或则基类拥有析构函数的情况下它才会自动合成析构函数.如果成员变量或则基类拥有析构函数, 则编译器一定会合成析构函数, 负责调用成员变量或则基类的析构函数, 此时如果用户提供了析构函数,则编译器会在用户析构函数之后添加上述代码.类析构的顺序为: 派生类析构函数, 对象成员析构函数, 基类析构函数.*声明本文于网络整理版权归原作者所有如来源信息有误或侵犯权益请联系我们删除或授权事宜。戳“阅读原文”我们一起进步