浅拷贝:
浅拷贝是指我们没有提供拷贝构造函数,使用编译器默认生成的拷贝构造函数,导致程序只是拷贝了一份数据,没有为新的对象开辟属于自己的内存空间,释放的时候调用的是同一个析构函数,先调用成功的释放了,后调用的对象一析构,程序就崩溃了
解决方法:
解决方法是,我们自己提供一个拷贝构造函数,在拷贝构造的时候,帮新对象开辟一块内存空间,并且重载=操作符,两个指针分别指向自己的那一块内存,互不影响(内容一样,地址不同),每个对象都拥有自己的资源
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
Person(char* name, int age)
{
_name = new char[strlen(name) + 1];
strcpy(_name, name);
_age = age;
}
#if 0
//自己提供拷贝构造函数
Person(const Person& p)
{
_name = new char[strlen(p._name) + 1];
strcpy(_name, p._name);
_age = p._age;
}
#endif
//重载=运算符
Person& operator=(const Person& p)
{
if (_name == p._name)
{
return *this;
}
_name = new char[strlen(p._name) + 1];
strcpy(_name, p._name);
_age = p._age;
return *this;
}
private:
char* _name;
int _age;
};
void Test()
{
Person a("张三", 19);
//Person b(a);
Person b("李四", 19);
b = a;
printf("%p\n", a);
printf("%p\n", b);
}
int main()
{
Test();
system("pause");
return 0;
}
但是这里面多次调用了new 和strcpy,导致代码利用率不是很高,所以采用现代版string类写法
#include<algorithm>
class String
{
public:
String(const char* name="")
{
_name = new char[strlen(name) + 1];
strcpy(_name, name);
}
#if 0
String(const String& s) :_name(nullptr)
{
String stemp(s._name);
swap(_name, stemp._name);
}
#endif
private:
char* _name;
};
void Test()
{
String s("张三");
String b(s);
printf("%p\n", s);
printf("%p\n", b);
}
int main()
{
Test();
system("pause");
return 0;
}
- s对象和b对象中的值是一样的,地址也一样
- 同一份资源析构两次,就会导致程序崩溃
- 提供了拷贝构造函数后,_name的值一样,但是地址却不一样,这个时候析构就不会崩溃
过程图示:
很早以前的忘了发的,补在这个博客里
握手为什么是三次?
- 为了证明双方都有数据收发的能力
- 确保服务端不会为迟到的重复SYN建立连接
- SYN和ACK只是两个标志位,没必要分两次报文发送
挥手为什么是四次?
- 因为被动关闭方的ACK和FIN请求不可以同时发送
为什么被动关闭方ACK和FIN不可以同时发送?
- 因为被动关闭方,收到FIN请求报文后,立即进行ACK回复,接下来需要等待用户调用close接口进行确认缓冲区的数据已经处理完毕/不关心这些数据了,才会像对方发送FIN请求报文,得到ACK回复后,直接释放socket,因此被动关闭方的FIN和ACK不可以同时发送