深拷贝和浅拷贝
浅拷贝就是将
源对象的值拷贝给当前对象,两者指向的还是同一地址,对一个对象的修改可能会影响到另一个对象。
class MyArray {
public:
// 构造函数
MyArray(int size) {
this->size = size;
data = new int[size];
}
// 拷贝构造函数,实现浅拷贝
MyArray(const MyArray& other) {
size = other.size;
data = other.data; // 浅拷贝,将指针复制给新对象
}
private:
int size;
int* data;
};深拷贝是 一种
对象拷贝,它会创建一个新的对象,并将原始对象中的所有数据成员复制到新的对象中,包括多态分配内存。原始对象和新的对象是完全独立的,对一个对象的修改不会影响另一个对象。
#include <iostream>
#include <cstring>
#pragma warning(disable : 4996)
using namespace std;
class Person {
public:
char* name; // 姓名
int age; // 年龄
Person(const char* name, int age) {
this->name = new char[strlen(name) + 1];
strcpy(this->name, name);
this->age = age;
}
// write your code here......
Person(const Person& p)//拷贝构造函数
{
this->name = new char[strlen(p.name) + 1];
strcpy(this->name, p.name);
this->age = p.age;
}
void showPerson() {
cout << name << " " << age << endl;
}
~Person() {
if (name != nullptr) {
delete[] name;
name = nullptr;
}
}
};
int main() {
char name[100] = { 0 };
int age;
// 用户输入姓名和年龄
cin >> name;
cin >> age;
//
Person p1(name, age);
// 实现浅拷贝
Person p2 = p1;
p2.showPerson();
return 0;
}区别:
- 对象中含有
指针类型的成员变量时需要用深拷贝构造,否则用浅拷贝构造- 编译器
默认的拷贝构造函数是浅拷贝构造函数- 如果对象中
含有指针用了浅拷贝构造,那么会导致两个指针变量指向同一块地址空间,如果没有创建内存的操作就是浅拷贝,否则就是深拷贝深拷贝可以用于创建独立的副本,对于需要完全独立的对象的情况,必须在修改副本时不影响原始对象的状态。而浅拷贝通常用于创建共享对象,当需要多个共享相同的数据时,可以使用浅拷贝来减少内存占用和提高性能。
友元函数
友元函数只是一个普通函数,并不是该类的类成员函数,它可以在任何地方调用,友元函数中通过对象名来访问该类的私有或保护成员。
friend <类型> <友元函数名>(<参数表>);
#include <iostream>
using namespace std;
class A
{
public:
A(int _a):a(_a){};
friend int geta(A &ca); // < 友元函数
private:
int a;
};
int geta(A &ca)
{
return ca.a;
}
int main()
{
A a(3);
cout<<geta(a)<<endl;
return 0;
}友元类
friend class <友元类名>类B是类A的友元,那么类B可以直接访问A的私有成员
- 友元关系
没有继承性- 友元关系
没有传递性
#include <iostream>
using namespace std;
class A
{
public:
A(int _a):a(_a){};
friend class B;
private:
int a;
};
class B
{
public:
int getb(A ca) {
return ca.a;
};
};
int main()
{
A a(3);
B b;
cout<<b.getb(a)<<endl;
return 0;
}swap函数
// 支持多种类型
swap(a,b); // 交换a和b的值,switch连续
在使用
switch的case时,遇到区间的情况,可以使用...来省略中间连续的数据。
#include <iostream>
using namespace std;
int main() {
int month;
cin >> month;
// write your code here......
if(month < 1 || month > 12)
cout << "不合法" <<endl;
else{
switch (month) {
case 3 ... 5: //可以使用连续的数
cout<<"春季"<<endl;
break;
case 6 ... 8:
cout<<"夏季"<<endl;
break;
case 9 ... 11:
cout<<"秋季"<<endl;
break;
default:
cout<<"冬季"<<endl;
}
}
return 0;
}输出
作用永久,贯穿整个程序,直到格式状态改变设置为其他函数
// 设置输出格式
dec //置基数位10,相当于%d
hex // 置基数位16,相当于%x
oct // 置基数位8,相当于%o
cout << 12 << endl;//默认十进制
cout << dec << 12 << endl;//十进制
cout << hex << 12 << endl;//十六进制
cout << oct << 12 << endl;//八进制
// 设置保留一个小数
cout << fixed << setprecision(1);运行状态
就绪: 除了CPU资源,获得了所有必要资源,只要获取CPU,便可立即执行,进行此时状态为就绪状态,当一个系统中处于就绪状态的进程可能有多个,排成一个队列 –就绪队列
阻塞:正在执行的进程,由于等待某个事件(缺外部资源)发生 而无法执行,便放弃CPU而处于阻塞状态。
动态分区分配算法
在动态分区分配方式中,当很多个空闲分区 都能满足需求时,如何选择
首次适应算法First Fit
每次都从
低地址开始查找,找到第一个能满足大小的空闲分区
最佳适应算法 Best Fit
为了保证
大进程到来时能有连续得到大片空间。空闲分区按容量递增次序链接,每次分配内存时顺序查找空闲分区链(或空闲分区表),找到大小满足要求的第一个空闲分区。
最坏(大)适应算法
每次分配优先
使用最大的连续空闲区,这样分配后剩余空闲区不会太小,更方便使用,空闲分区按容量递减次序链接,每次分配内存时顺序查找空闲分区链或空闲分区表,找到大小能满足要求 的第一个空闲分区
- 临近适应算法
空闲分区以地址
递增的顺序排列(可排成一个循环链表),每次分配内存时从上次查找结束的位置开始查找空闲分区链(或空闲分区表),找到大小能满足要求的第一个空闲分区。
网络层次
LLC:逻辑链路层,主要负责站点间的帧交换,差错控制,流量控制,应答功能。
this指针
this指针是类的指针,指向对象的首地址.this实际上是成员函数的一个
形参,在调用成员函数时将对象的地址作为实参传递给this,this指针只能在成员函数中使用。在静态成员函数中不能用this
非静态成员都包含一个特殊的指针,指向调用该函数的对象,这个指针成为this指针
特点
- 只能在成员函数中会用,
全局和静态函数,友元函数没有this指针 - this在成员函数的
开始前构造,在成员函数的结束后清除 - this指针不能被修改和赋值(它存放的是某一类对象地址)
this指针是一个隐含指针,是类成员函数的第一个默认参数,在函数体内可隐含使用它来访问本类的数据成员和成员函数,它并由编译器自动维护传递this指针是局部变量- this指针只有在
对象调用成员函数时才被初始化重新定向,进入后不能再被修改 this并不是对象的一部分,不影响sizeof结果。
const区分重载
#include<iostream>
using namespace std;
class Person
{
public:
void sum() const
{
int a = 1;
int b = 2;
cout << a + b << endl;
};
void sum()
{
int a = 2;
int b = 4;
cout << a + b << endl;
};
};
int main()
{
Person p;
const Person q;
p.sum();
q.sum();
return 0;
}字符串相等问题
#include <iostream>
using namespace std;
int main()
{
char str1[] = "hello world";
char str2[] = "hello world";
const char str3[] = "hello world";
const char str4[] = "hello world";
const char* pstring1 = "hello world";
const char* pstring2 = "hello world";
//数组不对比不相等
cout << boolalpha << (str1 == str2) << ',';
cout << boolalpha << (str3 == str4) << ',';
cout << boolalpha << (pstring1 == pstring2) << endl; //相等
return 0;
}字符函数
| 字符判断函数 | 作用 |
|---|---|
isalpha() |
判断字符是否是字母(‘a’-‘z’ ‘A’-‘Z’) |
isdigit() |
判断字符是否是数字 |
isspace() |
判断字符是否是空格、制表符、换行等标准空白 |
isalnum() |
判断字符是否是字母或者数字 |
ispunct() |
判断字符是标点符号 |
islower() |
判断字符是否是小写字母(‘a’-‘z’) |
isupper() |
判断字符是否是大写字母(‘A’-‘Z’) |
// 使用字符函数统计字符串中各类型字符的个数
#include <cctype>
#include <iostream>
#include <string>
using namespace std;
int main() {
string str;
getline(cin, str);
int whitespace = 0;
int digits = 0;
int chars = 0;
int others = 0;
// write your code here......
for(int i = 0;i<str.size();i++)
{
if(isalpha(str[i]))
{
chars++;
}
else if(isdigit(str[i]))
{
digits++;
}
else if(isspace(str[i]))
{
whitespace++;
}
else {
others++;
}
}
cout << "chars : " << chars
<< " whitespace : " << whitespace
<< " digits : " << digits
<< " others : " << others << endl;
return 0;
}反转链表的实现
给定一个单链表的头结点
pHead该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。
数据范围: 0≤10000≤n≤1000
要求:空间复杂度 O(1) ,时间复杂度 O*(n) 。
正解迭代
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) : val(x), next(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @return ListNode类
*/
ListNode* ReverseList(ListNode* head) {
// write code here
ListNode* pre = nullptr; //记录前一个节点,并作为链表反向指针
ListNode* cur = head; // 当前节点指针
ListNode* nex = nullptr; //指向下一个节点指针
while(cur!=nullptr)
{
//为nex节点指向指针
nex = cur->next;
// 将当前节点的next指针转向
cur->next = pre;
// 前驱节点后移
pre = cur;
// 当前节点同时也后移
cur = nex; //当前节点后移
}
return pre;
}
};- 获取前最大的k个值,使用最大堆,最小的话,使用最小堆。

