自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(58)
  • 收藏
  • 关注

原创 TCP编程流程和粘包

当服务端recv()第一个字符 ‘h’ 后,此时客户端的recv()正处于阻塞状态(客户端的接收缓冲区为空),send()一个 "ok" 到发送缓冲区并传递给客户端的接收缓冲区,还没等到服务端recv()第二个字符 ‘e’ 后send()第二个 "ok" ,客户端就已经recv()了其接收缓冲区中的 “ok” ,此时客户端的接收缓冲区只有一个 “ok”。1、发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。

2023-07-16 10:12:26 589

原创 Socket编程接口API并实现简单的TCP网络编程

recvfrom()读取 sockfd 上的数据,buff 和 len 参数分别指定读缓冲区的位置和大。recv()读取 sockfd 上的数据,buff 和 len 参数分别指定读缓冲区的位置和大小。accept()从 listen 监听队列中接收一个连接,成功返回一个新的连接 socket,listen()创建一个监听队列以存储待处理的客户连接,成功返回 0,失败返回-1。socket()创建套接字,成功返回套接字的文件描述符,失败返回-1。应答确认,超时重传,去重,乱序重排,滑动窗口(进行流量控制)

2023-07-09 22:43:35 614

原创 网络字节序和套接字

TCP/IP 协议族有 sockaddr_in 和 sockaddr_in6 两个专用套接字地址结构体,它们分别用于 IPV4 和 IPV6。在两台使用不同字节序的主机间传递数据时,会存在冲突。所以,在将数据发送到网络时规定整形数据使用大端字节序,所以也把。高位字节存储在内存的低地址处,低位字节存储在内存的高地址处。高位字节存储在内存的高地址处,低位字节存储在内存的低地址处。相当于指针中的 void* 指针一样可以接收任何类型的指针。大端字节序和小端字节序。

2023-07-06 21:47:25 242

原创 网络分层模型以及通信流程

将一个大的问题进行拆分,分而治之,专门的层处理专门的事情。而且那层出现问题只需对该层进行处理,不会影响到其他层。就相当于做菜的过程,从买菜到洗菜,再到切菜再炒,最后做完菜。买菜,洗菜,切菜和炒菜都有专门的人进行。头部长度为4位二进制,填满即为1111,转化为十进制为15即最多有15行,每行32位二进制即4字节,所以最大为60字节。一般头部固定部分为5行,也就是20字节。Tcp/ip模型早于ISO的OSI模型。通信过程相当于快递的邮寄过程。

2023-07-04 10:00:00 163

原创 Linux网络概念

假定MAC地址就是广播地址,那么所有接受过MAC包的路由器都会把这个消息进行转发,因此目标机器会收到很多重复的包(因为各个接受过该包的路由器都将其转发)。MAC地址是全球唯一的。IPV6(为128位二进制,每个段为16个位,每段用十六进制表示,格式类似为:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX)X为十六进制数,范围为0~f。如果不使用IP地址,那么就需要维护一个极其庞大的MAC地址表,在查找目的机器的时候,就需要向全世界发送数据包,可想而知会造成多大的网络流量。

2023-07-03 08:23:28 302

原创 Linux多线程与fork()函数

当如果多出使用fork()函数这样的方法比较繁杂,于是就使用函数pthread_atfork(父进程加锁函数,父进程解锁函数,子进程解锁函数),当程序中使用fork()函数时,会先调用父进程加锁函数,然后在fork()结束后在父进程调用父进程解锁函数,然后在子进程中调用子进程解锁函数。当去掉上述代码中的sleep()语句后,复制子进程时,子进程的锁的状态就变成不确定随机的,因为是在启动父进程的子线程后才开始复制的,复制时可能子线程加锁还没解锁,也可能子进程加完锁又解开了。此时子进程启动的为父进程的。

2023-06-30 13:00:01 367

原创 Linux线程安全

strtok()函数内部只有一个静态变量指针,同一个进程的所有线程在使用strtok()函数时,共用同一个静态变量指针,导致,在第一次主线程中。多线程程序无论调度顺序如何,都能得到正确的结果,就处于线程安全的状态。后,子线程调用strtok()函数使指针指向从。的字符串空间导致之后主线程和子线程都分割的是。例如:strtok()/strtok_r()

2023-06-27 11:00:00 41

原创 Linux线程同步

信号量,互斥锁,条件变量,读写锁对程序的执行过程进行控制,保证对临界资源的访问同一时刻只能有一个进程或线程访问。

2023-06-25 23:00:00 383

原创 Linux线程概念与创建

在执行时会出现两种情况,有时候只打印5个。

2023-06-23 22:14:07 581

原创 C++完美转发和forward

由于存在 Ty&&这种未定的引用类型,当它作为参数时,有可能被一个左值引用或者右值引用的参数初始化,这时经过类型推导的 Ty&&类型,相比右值引用 (&&)会发生类型的变化,这种变化被称为引用折叠。C++11中的引用折叠规则如下:(1)所有的右值引用叠加到右值引用上仍然还是一个右值引用。(2)所有的其他引用类型之间的叠加都将变成左值引用。C++11中提供了这样的一个函数std::forward,它是为转发而生的,不管参数是T&&这种未定的引用还是明确的左值引用或者右值引用,它会按照参数本来的值类型转发。

2023-06-23 11:15:00 57

原创 C++std::move函数的实现

void fun(_Ty&& x)//参数的形式为行为未定义int z=10;_Ty y=z;fun(a);//在fun函数中x为int&类型,_Ty也为int&类型fun(b);//在fun函数中x为const int&类型,_Ty也为const int&类型fun(30);//在fun函数中x为int&&类型,而_Ty为int类型//实参为左值,推导的x就为左值引用;实参为常性左值,推导的x就为常性左值引用;实参为右值,推导的x就为右值引用。

2023-06-22 10:30:00 135

原创 C++静态对象的移动问题

不使用移动函数以值的形式返回对象时,是否调用移动拷贝构造函数去构建将亡值取决于返回值本身。如果是非常性非静态局部的变量返回时则会调用移动拷贝构造函数,否则会调用普通的深拷贝构造函数。如果使用移动函数std::move()时,只会将非常性对象转换为右值,比如普通变量、静态变量、全局变量均可以通过其转换为右值。

2023-06-21 20:51:55 320

原创 C++移动函数->std::move()

很明显,对于常性的s1对象,使用移动函数并没有强行移动其资源,而是调用普通的拷贝构造进行深拷贝,原因是引用叠加;而强转则是强行移动该常性对象的资源。所以在使用时尽量使用移动函数而不使用强转,因为强转是破坏语法规则来进行的。在语法规则上,s1为左值不能调用移动拷贝构造,但实际上是使用强转进行语义的转换,将s1从左值强转为右值。但如果没有移动拷贝构造或者移动赋值函数,就会退而求其次调用参数为常性左值引用的函数。使用移动拷贝将s1拷贝给s3后,s1.pstr就变为空了。

2023-06-20 10:30:00 191

原创 C++右值引用问题

返回时,使用tmp对象构建将亡值对象xvalue,同样的,在堆区申请和tmp所申请大小相同的空间,将字符串"helloworld"赋值过去进行存放,xvalue.str指向该堆区空间。回到main函数时,将将亡值xvalue赋值给s1对象时,调用移动赋值函数,将xvalue的资源再次移动给s1对象,赋值结束后xvalue将亡值对象消亡,打印s1的内容,析构所有对象程序结束。同样的,运行时进入主函数,首先创建s1对象,在堆区空间申请空间存放字符串"hello",s1.str指向该堆区空间。

2023-06-19 23:01:35 435

原创 C++11特性之左值引用和右值引用

引用本质上是指针,在以引用返回时不会构建将亡值,而是直接将tmp对象的地址返回,返回结束后fun函数的栈空间被系统收回,tmp对象已经消亡,用已经消亡的对象去初始化a对象或者引用已死亡的对象是错误的,此时的引用b和c都是。右值引用引用将亡值后,将亡值的生存期就随从右值引用的标识符的生存期,而右值引用rf为静态右值引用,存储在.data区,.data区的数据是在程序运行结束才进行释放,所以当整个程序结束才会销毁该将亡值。由此来看,使用右值引用去引用将亡值,该将亡值的生存期就会和右值引用的标识符相同。

2023-06-17 20:30:00 292

原创 C++动态转换

基类中必须至少有一个虚函数,否则编译失败。使用异常给程序增加了相应的运行开销,所以尽可能使用引用的dynamic_cast。

2023-06-17 10:00:00 514

原创 C++重新解释转换

用法:reinterpret_cast < type_name >(expression) 说明:type_name必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针。注意:reinterpret_cast主要是将数据从一种类型的转换为另一种类型。所谓"通常为操作数的位模式提供较低层的重新解释”也就是说将数据以二进制存在形式的重新解释。,由于Windows系统是小端存储,所以先打印低位的0x64,其ASCII值对应字符为d;

2023-06-16 21:38:48 114

原创 C++去常性转换

用法:const_cast< type_name >(expression) 说明:该算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, typename和expression的类型是一样的。注意: 常量指针被转化成非常量的指针,并且仍然指向原来的对象;常量引用被转换成非常量的引用,并且仍然引用原来的对象。原因就是在C++中,对于常变量在编译时会将其替换为值本身。

2023-06-15 11:15:00 215

原创 C++静态转换

用法:static_cast<type_name> (expression) 说明:该运算符把expression转换为type_name类型static_cast 在编译时使用类型信息执行转换在转换执行必要的检测诸如指针越界计算,类型检查等);但没有运行时类型检查来保证转换的安全性。

2023-06-14 23:02:14 1442

原创 C++11的final和override关键字及动态和静态多态的优缺点

override 关键字确保在派生类中声明的重写函数与基类的虚函数有相同的签名,同时也明确表明将会重写基类的虚函数,还可以防止因疏忽把本来想重写基类的虚函数声明成隐藏。动态多态中接口是显式的,以函数签名为中心,多态通过虚函数在运行期实现,静态多台中接口是隐式的,以有效表达式为中心,多态通过模板具现在编译期完成。静态多态缺点:由于是模板来实现静态多态,因此模板的不足也就是静多态的劣势,比如调试困难、编译耗时、代码膨胀、编译器支持的兼容性不能够处理异质对象集合。

2023-06-14 09:30:00 675

原创 C++设计模式

一个Gimme依次问她妈、爸、爷、奶请求要礼物,如果有一个人回应YES应答则结束,否则Gimme继续问下一个人请求要礼物,直到所有人请求完。一个青蛙是呱呱叫在被小女孩kiss后,有一半几率变成王子是叫达林,另一半概率变成狗是汪汪叫。该程序实现统计一个字符串中的单词的个数,对于not's和new-data都作为一个单词。

2023-06-13 22:30:00 40

原创 C++虚析构函数、纯虚函数和抽象类

1、构造函数的用途: 1)创建对象,2) 初始化对象中的属性,3) 类型转换2、在类中定义了虚函数就会有一个虚函数表,对象模型中就含有一个指向虚表的指针(_vfptr)。在定义对象时构造函数设置虚表指针指向虚函数表。3、使用指针和引用调用虚函数,在编译只需要知道函数接口,运行时指向具体对象,才能关联具体对象的虚方法(通过虚函数指针查虚函数表得到具体对象中的虚方法)。

2023-06-13 09:05:15 1146

原创 C++静态联编和动态联编

在构造函数、拷贝构造函数或者析构函数中调用虚函数,一定是调用本类的虚函数,如果本类没有重写虚函数,则调用基类的虚函数。在构造、拷贝构造、析构函数中调用虚函数时编译器一律采用静态联编的方式,而不使用动态联编。

2023-06-09 21:37:53 787

原创 C++多态性

类的成员函数定义为虚函数,但必须注意以下几条:1.派生类中定义虚函数必须与基类中的虚函数同名外,还必须同参数表,同返回类型。如果是函数名和返回值类型相同参数列表不同被认为是同名隐藏,不具有多态性;如果是函数名和参数列表相同但返回值类型不同则会编译报错,不协变,但如果去掉虚关键字则能编译通过,但使用时存在二义性。如基类中返回基类指针,派生类中返回派生类指针是允许的,这是一个例外(协变)。2.只有类的成员函数才能说明为虚函数。这是因为虚函数仅适用于有继承关系的类对象。友元函数和全局函数也不能作为虚函数。

2023-06-09 10:30:00 72

原创 C++多重继承与派生类成员标识

有了多继承,就存在菱形继承,有了菱形继承就有菱形虚拟继承,底层实现就很复杂。所以一般不建议设计出多继承,不要设计出菱形继承。否则在复杂度及性能上都有问题。虚基类是指继承方式是虚的,派生类对象中不会存在虚基类无名对象,而是一个偏移量或者是指针,也就导致在派生类中人对象只有一份。

2023-06-08 23:40:51 59

原创 C++继承和静态成员

总结:Person 基类中设计了static静态成员 num ,在基类外初始化。则整个继承体系里面只有一个静态num成员。Student类在继承时是以左边的实例化类为基类进行继承,Employee类在继承时是以右边的实例化类为基类进行继承的,二者的num是不同的num。但如果Student类和Employee类继承的实例化类型相同,则num依然是同一个num。继承与静态成员,静态成员只有一个,所有对象共享(包括基类对象和派生类对象)。模板是产生代码的代码,模板Person类会分裂成两个实例化的类。

2023-06-07 10:00:00 132

原创 C++单例模式

只能创建一个对象。

2023-06-07 00:34:38 28

原创 C++公有继承(是一个的关系)

但如果自己在派生类中给出拷贝构造函数,但未明确调用基类拷贝构造,在运行时系统将会自己调用默认的基类构造函数,这样就会导致数据拷贝存在错误。同样的,对于赋值运算符重载函数,如果在派生类中没有明确调用基类的赋值函数,则派生类对象基类属性的值不会发生改变。易于修改被复用的代码。2.可以将一个派生类的对象的地址赋给其基类的指针变量,但只能通过这个指针访问派生类中由基类继承来的隐藏对象,不能访问派生类中的新成员。1.派生类的对象可以赋值给基类的对象,这时是把派生类对象中从对应基类中继承来的隐藏对象赋值给基类对象。

2023-06-05 09:00:00 173

原创 C++继承与派生

派生反映了事物之间的联系,事物的共性与个性之间的关系。派生与独立设计若干相关的类,前者工作量少,重复的部分可以从基类继承来,不需要单独编程。继承是类型设计层面上的复用。

2023-06-04 23:00:00 543

原创 C++类模板

template<类型模板参数表>class 类名//类声明体//分号不可少template<类型模板参数表>返回类型 类名<模板参数表>::成员函数名1(形参表)//成员函数定义体template<类型模板参数表>返回类型 类名<模板参数表>::成员函数名n(形参表)//成员函数n定义体//类型重命名的过程被称为模板实例化 template instantiation模板参数有两种: 模板类型参数和模板非类型参数。

2023-06-04 18:14:09 30

原创 C++组合关系中的为问题和实例

不能在类中定义类自身,否则会造成无穷递归:也叫做不完整类型而可以在类中定义静态类自身,因为静态变量只有一份,不会形成递归;也可以在类中定义类自身指针,因为在创建对象时,不需要使用对象实体给指针进行赋值,没有实体对象就不会进行无限递归;

2023-06-03 10:00:00 127

原创 C++对象间的关系

(有一个,"用...来实现”,用...来构成”,有整体和部分的关系)组合关系用一条带实心菱形箭头直线表示,如下图表示Body和Soul组成People,或者People由Body和 Soul组成与聚合关系一样,组合关系同样表示整体由部分构成的语义;但它们差别是,聚合关系所涉及的两个类型的对象,在现实世界中的含义有明显的has -a(有一个)的语义,能够区分那个是整体,那个是部分,而关联所涉及的对象之间没有这种语义,即分不出整体和部分的关系。所以,关联关系是一种“强关联”的关系;但以指针和引用是有区别的;

2023-06-02 23:23:19 136

原创 C++静态成员

1设计静态数据成员目的是信息共享,和信息交流2.类的静态数据成员为所有类对象所共享,不属于某个具体的实例3.类的静态数据成员必须在类外定义,定义时不添加static关键字,不能在构造函数的初始化列表中创建4.类的静态数据成员类型是int,short, char,long long,并且是const,可以在类中直接初始化,也可以在类外初始化5.在类的成员函数中使用静态数据成员静态数据成员之前没有this。

2023-06-02 11:00:00 33

原创 C++友元

1.友元函数不是类的成员函数,在函数体中访问对象的成员,必须用对象名加运算符“."加对象成员名。但友元函数可以访问类中的所有成员,一般函数只能访问类中的公有成员2.友元函数不受类中的访问权限关键字限制,可以把它放在类的公有、私有、保护部分,但结果一样3.某类的友元函数的作用域并非该类作用域。如果该友元函数是另一类的成员函数,则其作用域为另一类的作用域,否则与一般函数相同。

2023-06-01 20:00:00 28

原创 C++函数返回值与左值

这样普通对象会调用普通函数获取值,修改值;而常对象则会调用常方法获取值,但不能更改,因为其返回值为常引用。常方法可以和普通方法进行重载。函数的返回值类型为引用时,其返回值为左值,可以被赋值;函数的返回值类型为普通值时,为右值(将亡值)。函数能被赋值的条件是,函数返回值是左值,而函数返回值为左值的条件就是函数的返回值类型为引用。但这样的函数对于常对象无法使用。

2023-06-01 14:59:03 133

原创 C++运算符重载

1、运算符重载函数的函数名必须为关键字operator加一个合法的运算符。在调用该函数时,将右操作数作为函数的实参。2、当用类的成员函数实现运算符的重载时,运算符重载函数的参数(当为双目运算符时)为一个或(当为单目运算符时)没有。运算符的左操作数一定是对象,因为重载的运算符是该对象的成员函数,而右操作数是该函数的参数。

2023-05-31 17:57:01 47

原创 C++仿写String类与返回值

第一种运算符重载方法在使用过程中会构造两个对象,一个是局部对象tmp,另一个是将亡值对象,多次的构造和销毁对象会造成程序效率降低;而方法二只构建一个tmp对象,并将其以引用形式返回,这样存在问题,就是不能将局部变量以引用或者指针的形式返回(在15.2中介绍)。但第三种方法在使用过程中就只构建一次对象。针对主函数的方案不同,第一种是先构造对象,再进行赋值,这样会调用调用构造函数和赋值运算符重载函数,第二种是构建并进行初始化,此处会直接调用拷贝构造函数。

2023-05-30 23:13:33 80

原创 C++仿写String之右值引用与移动语义

14.1右值引用无法取地址的值或者是能放入寄存器的值称为右值,不论哪种值只要具名就是左值。C++11没有给出常性右值引用的使用场景,但在语法规则层面是存在其正确的。

2023-05-28 23:30:00 98

原创 C++仿写String类之赋值运算符重载

13.1基本概念为了满足对象给对象赋值,而原有的赋值符(=)无法实现,于是就有了赋值运算符的重载。对于函数名必须是合法的标识符,=是不能作为有效的函数名的,所以C++就提供了operator关键字使得=可以作为有效的函数名。在类中如果没有显式给出赋值运算符重载函数时,则C++编译器自动给出一个赋值运算符重载函数。格式:类名& operator=(const 类名& 参数)

2023-05-28 18:35:10 82

原创 C++仿写String类之深拷贝和浅拷贝

在构建对象时要么调用构造函数,要么调用拷贝构造函数,必然调用其中一个,但不会二者同时调用。一定要注意构造函数和拷贝构造函数在编写时思路和代码是基本相同的,二者都具有构建和初始化对象的能力。

2023-05-26 10:00:00 37

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除