怎样做网站别人能访问,搜索引擎优化哪些方面,网站开发人员 平均工资,深圳东门老街游玩攻略推荐C/C复习 day1 文章目录 C/C复习 day1前言一、C语言1.memcpy函数2.memmove函数3.strstr函数4.宏定义的函数5.大小端的介绍以及判断 二、C入门基础1.C是如何支持函数重载的#xff1f;2.建议用const enum inline去替代宏 三、C类和对象1.类大小的计算2.移动构造和移动赋值1.右值…C/C复习 day1 文章目录 C/C复习 day1前言一、C语言1.memcpy函数2.memmove函数3.strstr函数4.宏定义的函数5.大小端的介绍以及判断 二、C入门基础1.C是如何支持函数重载的2.建议用const enum inline去替代宏 三、C类和对象1.类大小的计算2.移动构造和移动赋值1.右值引用2.move关键字3.模板右引用4.完美转发5.移动构造和移动赋值 3.初始化列表1.初始化列表的特性2.哪些类型必须在初始化列表中初始化 4.运算符重载1. 不支持重载的运算符2.自定义类型转化内置类型 3. 内存管理1.new delete 和 malloc free的区别2.new 和 new[]底层实现原理3.内存泄露问题1.什么是内存泄漏2.内存泄漏的危害3.如何解决内存泄漏1.RAII 智能指针2.使用内存泄漏检查工具 总结 前言
随着C课程的学习结束接下来回顾一下C和C中的难点看看有什么是遗漏的。 一、C语言
1.memcpy函数
void* my_memcpy(void* des, const void* src, size_t num)
{assert(des ! NULL src ! NULL);void* begin des;for (size_t i 0; i num; i){*(char*)des *(char*)src;des (char*)des 1;src (char*)src 1;}return begin;
}按照字节数去拷贝赋值
2.memmove函数
// 从右往左移动则小到大赋值 从左往右复制则从大到小赋值
void* my_memmove(void* des,const void* src,size_t num)
{assert(des!NULL src!NULL);void* begin des;if (des src){for (size_t i 0; i num; i){*(char*)des *(char*)src;des (char*)des 1;src (char*)src 1;}}else{for (size_t i num-1; i!-1; i--){*((char*)des i) *((char*)src i);}}return begin;
}注意赋值顺序
3.strstr函数
char* my_strstr(char* str1,const char* str2)
{int i 0, j 0;int flag 0;char* begin NULL;char* p1 str1, *p2 str2;while (p1[i] ! \0 p2[j] ! \0){if (p1[i] p2[j]){if (flag 0){begin p1i;flag 1;}i;j;}else{i i - j 1;j 0;flag 0;}}if (p2[j] \0){return begin;}else{return NULL;}
}4.宏定义的函数
#define ADD(x,y) ((x)(y))5.大小端的介绍以及判断
大小端
int main()
{// 判断大小端 01 00 00 00 01// 大端 01 02 03 04// 00 00 00 01// 小端 01 02 03 04// 01 00 00 00int i 1;if (*(char*)i 1){printf(小端\n);}else if (*(char*)(i) 0){printf(大端\n);}
}二、C入门基础
1.C是如何支持函数重载的
函数重载 C支持函数重载而C语言不支持是因为函数在内存中的存储方式不相同C语言是直接以函数名修饰而C是_Z 函数名长度 函数名 类型首字母导致C支持重载而C语言不支持重载。
2.建议用const enum inline去替代宏
三、C类和对象
1.类大小的计算
类大小的计算 总结1.类大小的计算不包括static修饰的静态的一系列东西函数也不算在内。 2. 类大小的计算要符合结构体的对齐规则。 3. 空类的大小为1。 4. 虚函数(多态重写):要存放一个虚函数表先存该父类的虚函数表再存父类中的成员变量。 5. 虚继承父类中要多存放一个偏移量。
2.移动构造和移动赋值
说起这两个就必须先提起C11引入的右值引用和几个关键字。
1.右值引用
int rr110;
double rr2 xy;之前的一个表示对变量的引用现在两个表示对右值的引用。
2.move关键字
比如我们正常这样写编译器会报错不支持。 无法将左值绑定到右值引用。
int x10;
int rr1 x;但是我们通过move关键字即可完成。 move仅仅是将变量的右值取出。
int x10;
int rr1 std::move(x);3.模板右引用
对于模板来说对于它此时则既可以接受左值传参也可以接受右值传参。也就是万能引用。
void Fun(int x){ cout 左值引用 endl; }
void Fun(const int x){ cout const 左值引用 endl; }
void Fun(int x){ cout 右值引用 endl; }
void Fun(const int x){ cout const 右值引用 endl; }
templateclass T
void func(T value)
{fun(value);
}如果我们执行程序可以发现我们的输出全是左值引用这是为什么呢 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力 但是引用类型的唯一作用就是限制了接收的类型后续使用中都退化成了左值。 因此需要我们的完美转发。
4.完美转发
void Fun(int x){ cout 左值引用 endl; }
void Fun(const int x){ cout const 左值引用 endl; }
void Fun(int x){ cout 右值引用 endl; }
void Fun(const int x){ cout const 右值引用 endl; }
// std::forwardT(t)在传参的过程中保持了t的原生类型属性。
templatetypename T
void PerfectForward(T t)
{Fun(std::forwardT(t));
}通过forward模板(参数)即可实现完美转发使左值按左值传参右值按右值传参。
5.移动构造和移动赋值
移动构造和移动赋值 这样写避免了某些不必要的深拷贝。 noexcept关键字表示该函数不会抛出异常。 注意赋值完要对原对象进行处理这里指针将其变为nullptr
3.初始化列表
1.初始化列表的特性
效率优势 初始化列表在对象成员的初始化过程中效率更高。对于一些内置类型和没有默认构造函数的类类型成员如果在初始化列表中进行初始化能避免额外的默认初始化和赋值操作。初始化顺序 成员变量的初始化顺序是按照它们在类中的声明顺序而不是在初始化列表中的顺序。成员对象初始化 对于类中的成员对象使用初始化列表可以正确地调用其对应的构造函数进行初始化。避免未定义行为 如果不使用初始化列表对某些成员进行初始化可能导致未定义的行为尤其是对于具有复杂依赖关系的成员。
2.哪些类型必须在初始化列表中初始化
const成员变量
class MyClass {const int myConstVar;
public:MyClass(int val) : myConstVar(val) {} // 必须在初始化列表中初始化
};引用成员变量
class YourClass {int myRefVar;
public:YourClass(int var) : myRefVar(var) {} // 引用必须在初始化列表中初始化
};没有默认构造函数的类成员
class OtherClass {OtherClass(int x) {} // 自定义构造函数无默认构造函数
};class MainClass {OtherClass myOther;
public:MainClass(int val) : myOther(val) {} // 需在初始化列表中初始化
};基类 当从基类派生出一个类并且基类没有默认构造函数时则必须在初始化列表中进行初始化。
class Base {Base(int num) {}
};class Derived : public Base {
public:Derived(int num) : Base(num) {} // 初始化基类
};4.运算符重载
1. 不支持重载的运算符
作用域操作符 条件操作符 点操作符 .预处理操作符 #
2.自定义类型转化内置类型
可以通过重载内置类型来完成 例如以下代码将MyClass类转化为int类型此时重载函数不需要写返回值。
class MyClass {
private:int value;public:MyClass(int val) : value(val) {}operator int() {return value;}
};int main() {MyClass obj(42);int num obj; // 调用重载的 operator int 进行类型转换std::cout Converted value: num std::endl;return 0;
}3. 内存管理
1.new delete 和 malloc free的区别
区别
2.new 和 new[]底层实现原理
new 会调用operator new 先去开辟空间开辟完后再调用对应的构造函数进行初始化。new [] 会调用n次operator new去开辟空间然后再去调用n次构造函数进行初始化。
3.内存泄露问题
1.什么是内存泄漏
内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失而是应用程序分配某段内存后因为设计错误失去了对该段内存的控制因而造成了内存的浪费。 由于引入了异常问题在抛出异常后对应的内存可能没有进行释放久而久之就可能导致内存泄漏。
2.内存泄漏的危害
长期运行的程序出现内存泄漏影响很大如操作系统、后台服务等等出现 内存泄漏会导致响应越来越慢最终卡死。
3.如何解决内存泄漏
1.RAII 智能指针
auto_ptr 最早引入的智能指针但不支持赋值smart_ptr 支持赋值但是双链表的循环会出现问题。weak_ptr 不增加计数用来解决循环问题。
2.使用内存泄漏检查工具
总结
以上就是C/C的总结一接下来应该还有需要补充修改的内容。 本人小白一枚有问题还望各位大佬指正。