C++复习day05

news/2024/9/16 18:52:34/ 标签: c++, 算法

类和对象

1. 面向对象和面向过程的区别是什么?(开放性问题)
1. **抽象级别**:- **面向对象**:以对象(数据和方法的集合)为中心,强调的是数据和行为的封装。- **面向过程**:以过程(函数或子程序)为中心,强调的是步骤和顺序。2. **数据和方法的关系**:- **面向对象**:数据和处理数据的方法封装在对象中,对象可以包含数据和操作数据的方法。- **面向过程**:数据和处理数据的方法是分离的,通常数据结构和处理这些数据的函数是分开的。3. **模块化**:- **面向对象**:通过类和对象来实现模块化,类定义了对象的蓝图。- **面向过程**:通过函数和过程来实现模块化,函数是独立的代码块。4. **代码重用**:- **面向对象**:通过继承和多态性,可以更容易地重用代码。- **面向过程**:代码重用通常通过函数库来实现,但可能不如面向对象那样灵活。5. **维护和扩展**:- **面向对象**:由于封装和模块化,通常更容易维护和扩展。- **面向过程**:随着系统的增长,维护和扩展可能会变得更加困难。6. **设计复杂性**:- **面向对象**:设计可能更复杂,因为需要考虑类之间的关系和继承结构。- **面向过程**:设计可能更直接,因为关注点在于函数的调用和执行。7. **语言支持**:- **面向对象**:许多现代编程语言(如Java、C++、Python、Ruby)天然支持面向对象编程。- **面向过程**:几乎所有编程语言都支持过程化编程,但一些语言(如C)在支持面向对象特性方面可能不如其他语言。8. **性能**:- **面向对象**:可能会有额外的开销,因为需要处理对象的创建和方法调用。- **面向过程**:通常在性能上更高效,因为直接调用函数通常比创建对象和调用方法更快。
2.类大小的计算

这里同样是和结构体的内存对齐做法相同,需要注意的是空类的大小是1(主要是为了在地址空间中占位,表示存在这个类)

3.class和struct的区别
  1. struct 一般用于描述一个数据结构集合,而 class 是对一个对象数据的封装;
  2. struct 中默认的访问控制权限是 public 的,而 class 中默认的访问控制权限是 private 的,例如:
struct A{
int iNum; // 默认访问控制权限是 public
}
class B{
int iNum; // 默认访问控制权限是 private
}
  1. 在继承关系中,struct 默认是公有继承,而 class 是私有继承;
  2. class 关键字可以用于定义模板参数,就像 typename,而 struct 不能用于定义模板参数,例如:
template<typename T, typename Y> // 可以把typename 换成 class
int Func(const T& t, const Y& y) {
//TODO
}
3.this指针
1)this指针存放在哪里?

this指针是在栈上的,因为他是一个形参,当然有时候在会存在于寄存器上。因为有时候需要频繁的使用this指针,所以放到了寄存器,便于更加快速的使用this指针

2)this指针可以为空嘛?

this指针通常不能为nullptr,因为他是当前对象的地址,然而有一些特殊的情况

1. 静态成员函数:在静态成员函数中,this指针是不可用的,因为静态成员函数不依赖于任何特定的实例。
2 .如果是去调用成员函数,由于成员函数并不在对象中,this不会进行解引用,所以即使this是空指针,也不会崩溃。
3. 如果this指针是空,还访问了成员变量,那么成员就会崩溃,原因是对空指针进行了解引用。

4.八个默认成员函数

首先先整体清点一下是哪八个成员函数
构造函数,析构函数,拷贝构造函数,赋值运算符重载,取地址操作符重载,const成员函数,移动构造,移动赋值

1)构造函数
构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次。虽然名称叫构造,但是构造函数的主要任
务并不是开空间创建对象,而是初始化对象

特性:

1. 函数名与类名相同。
2. 无返回值。
3. 对象实例化时编译器自动调用对应的构造函数。
4. 构造函数可以重载。

问: 关于编译器生成的默认成员函数,很多童鞋会有疑惑:不实现构造函数的情况下,编译器会生成默认的构造函数。但是看起来默认构造函数又没什么用?d对象调用了编译器生成的默认构造函数,但是d对象_year/_month/_day,依旧是随机值。也就说在这里编译器生成的
默认构造函数并没有什么用??
答: C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如int/char…,自定义类型就是我们使用class/struct/union等自己定义的类型,看看下面的程序,就会发现编译器生成默认的构造函数会对自定类型成员_t调用的它的默认成员函数。

class Time
{
public:Time(){cout << "Time()" << endl;_hour = 0;_minute = 0;_second = 0;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:// 基本类型(内置类型)int _year;int _month;int _day;// 自定义类型Time _t;
};
int main()
{Date d;return 0;
}

注意:C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在类中声明时可以给默认值。

class Time
{
public:Time(){cout << "Time()" << endl;_hour = 0;_minute = 0;_second = 0;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:// 基本类型(内置类型)int _year = 1970;int _month = 1;int _day = 1;// 自定义类型Time _t;
};
int main()
{Date d;return 0;
}
2) 析构函数
析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由
编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

析构函数是特殊的成员函数,其特征如下:

  1. 析构函数名是在类名前加上字符 ~。
  2. 无参数无返回值类型。
  3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构
    函数不能重载
  4. 对象生命周期结束时,C++编译系统系统自动调用析构函数
  5. 关于编译器自动生成的析构函数,是否会完成一些事情呢?下面的程序我们会看到,编译器生成的默认析构函数,对自定类型成员调用它的析构函数。
  6. 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。
3) 拷贝构造

拷贝构造函数也是特殊的成员函数,其特征如下

  1. 拷贝构造函数是构造函数的一个重载形式
  2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用
  3. 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。
  4. . 编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,还需要自己显式实现吗?当然像日期类这样的类是没必要的。那么下面的类呢?验证一下试试?
// 这里会发现下面的程序会崩溃掉?这里就需要我们以后讲的深拷贝去解决。
typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 10){_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申请空间失败");return;}size = 0;_capacity = capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}~Stack(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}
private:DataType* _array;size_t _size;size_t _capacity;
};
int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2(s1);return 0;
}

这种情况是会崩溃的,因为同一块空间被释放了两次

4)运算符重载
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其
返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)

注意:

  • 不能通过连接其他符号来创建新的操作符:比如operator@
  • 重载操作符必须有一个类类型参数
  • 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
  • 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
  • .* :: sizeof ?: .这五类运算符是不能够被重载的,这个在笔试题中会经常性的出现
    比如我们重载一下Date类的==和<<,代码大概就像这样:
#include <iostream>using namespace std;class Date
{friend ostream& operator << (ostream& out, const Date& d);friend bool operator==(const Date& d1, const Date& d2);
public:Date(int year, int month, int day) :_year(year),_month(month),_day(day){ }~Date(){cout << "~Date()" << endl;}private:int _year;int _month;int _day;
};
bool operator==(const Date& d1, const Date& d2)
{return d1._year == d2._year && d1._month == d2._month && d1._day == d2._day;
}
ostream& operator << (ostream & out, const Date& d)
{out << d._year << d._month << d._day;return out;
}
int main()
{Date d1(1, 1, 1),d2(2,2,2);cout << (d1 == d2) << endl;;cout << d1 << endl;return 0;
}

赋值运算符重载格式:

  • 参数类型:const T&,传递引用可以提高传参效率
  • 返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
  • 检测是否自己给自己赋值
  • 返回*this :要复合连续赋值的含义
#include <iostream>using namespace std;class Date
{friend ostream& operator << (ostream& out, const Date& d);friend bool operator==(const Date& d1, const Date& d2);
public:Date(int year, int month, int day) :_year(year),_month(month),_day(day){ }Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}~Date(){cout << "~Date()" << endl;}const Date& operator=(const Date& d){_year = d._year;_month = d._month;_day = d._day;return *this;}
private:int _year;int _month;int _day;
};
bool operator==(const Date& d1, const Date& d2)
{return d1._year == d2._year && d1._month == d2._month && d1._day == d2._day;
}
ostream& operator << (ostream & out, const Date& d)
{out << d._year << d._month << d._day;return out;
}
int main()
{Date d1(1, 1, 1),d2(2,2,2);cout << (d1 == d2) << endl;d1 = d2 = Date(3,3,3);cout << (d1 == d2) << endl;return 0;
}

注意:

赋值运算符只能重载成类的成员函数不能重载成全局函数
用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。注意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符
重载完成赋值。

这里提一嘴关于前置++和后置++的实现(–也是同理的)

#include <iostream>using namespace std;class Date
{friend ostream& operator << (ostream& out, const Date& d);friend bool operator==(const Date& d1, const Date& d2);
public:Date(int year, int month, int day) :_year(year),_month(month),_day(day){ }Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}Date& operator++()// 前置++{_day += 1; //这里为例简便,我就不考虑什么月份,天数什么的了}Date operator++(int) //后置++{Date temp(*this);_day += 1;return temp;}~Date(){cout << "~Date()" << endl;}const Date& operator=(const Date& d){_year = d._year;_month = d._month;_day = d._day;return *this;}
private:int _year;int _month;int _day;
};
bool operator==(const Date& d1, const Date& d2)
{return d1._year == d2._year && d1._month == d2._month && d1._day == d2._day;
}
ostream& operator << (ostream & out, const Date& d)
{out << d._year << d._month << d._day;return out;
}
int main()
{Date d1(1, 1, 1),d2(2,2,2);cout << (d1 == d2) << endl;d1 = d2 = Date(3,3,3);cout << (d1 == d2) << endl;return 0;
}
5)const成员
将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。

请思考下面的几个问题:

  1. const对象可以调用非const成员函数吗?
  2. 非const对象可以调用const成员函数吗?
  3. const成员函数内可以调用其它的非const成员函数吗?
  4. 非const成员函数内可以调用其它的const成员函数吗?
const对象不可以调用非const成员函数,非const对象可以调用const成员函数。
const成员函数不可以调用其他的非const成员函数,非const成员函数可以调用const成员函数
6)取地址操作符重载

这两个默认成员函数一般不用重新定义 ,编译器默认会生成。
这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需
要重载,比如想让别人获取到指定的内容!

7/8) 移动构造和移动赋值

(这两个成员函数放到一起进行讨论)
首先来介绍一下什么叫做左值引用,什么叫做右值引用,以及他们的区别是什么

传统的C++语法中就有引用的语法,而C++11中新增了的右值引用语法特性,所以从现在开始我们之前学习的引用就叫做左值引用。无论左值引用还是右值引用,都是给对象取别名。
什么是左值?什么是左值引用?
左值是一个表示数据的表达式(如变量名或解引用的指针),我们可以获取它的地址+可以对它赋值,左值可以出现赋值符号的左边,右值不能出现在赋值符号左边。定义时const修饰符后的左值,不能给他赋值,但是可以取它的地址。左值引用就是给左值的引用,给左值取别名。
#include <iostream>
using namespace std;int main()
{int*p = new int(0);int b = 1;const int c = 2;int*&rp = p;int&pb = b;const int&pc = c;int&pvalue = *p;return 0;
}
什么是右值?什么是右值引用?
右值也是一个表示数据的表达式,如:字面常量、表达式返回值,函数返回值(这个不能是左值引用返回)等等,右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能取地址。右值引用就是对右值的引用,给右值取别名。
int main()
{
double x = 1.1, y = 2.2;
// 以下几个都是常见的右值
10;
x + y;
fmin(x, y);
// 以下几个都是对右值的右值引用
int&& rr1 = 10;
double&& rr2 = x + y;
double&& rr3 = fmin(x, y);
// 这里编译会报错:error C2106: “=”: 左操作数必须为左值
10 = 1;
x + y = 1;
fmin(x, y) = 1;
return 0;
}
需要注意的是右值是不能取地址的,但是给右值取别名后,会导致右值被存储到特定位置,且可以取到该位置的地址,也就是说例如:不能取字面量10的地址,但是rr1引用后,可以对rr1取地址,也可以修改rr1。如果不想rr1被修改,可以用const int&& rr1 去引用,是不是感觉很神奇,这个了解一下实际中右值引用的使用场景并不在于此,这个特性也不重要。
int main()
{double x = 1.1, y = 2.2;int&& rr1 = 10;const double&& rr2 = x + y;rr1 = 20;rr2 = 5.5;  // 报错return 0;
}

左值引用与右值引用比较
左值引用总结:

  1. 左值引用只能引用左值,不能引用右值。
  2. 但是const左值引用既可引用左值,也可引用右值。(临时常量具有常性)
#include <iostream>
using namespace std;int main()
{//int&a = 10;//这种是错误的const int&a = 10;//这种是正确的return 0;
}

右值引用总结:

  1. 右值引用只能右值,不能引用左值。
  2. 但是右值引用可以move以后的左值。

来看看右值引用使用场景和意义
前面我们可以看到左值引用既可以引用左值和又可以引用右值,那为什么C++11还要提出右值引
用呢?是不是化蛇添足呢?下面我们来看看左值引用的短板,右值引用是如何补齐这个短板的!

namespace bit
{class string{public:typedef char *iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}string(const char *str = ""): _size(strlen(str)), _capacity(_size){// cout << "string(char* str)" << endl;_str = new char[_capacity + 1];strcpy(_str, str);}// s1.swap(s2)void swap(string &s){::swap(_str, s._str);::swap(_size, s._size);::swap(_capacity, s._capacity);}// 拷贝构造string(const string &s): _str(nullptr){cout << "string(const string& s) -- 深拷贝" << endl;string tmp(s._str);swap(tmp);}// 赋值重载string &operator=(const string &s){cout << "string& operator=(string s) -- 深拷贝" << endl;string tmp(s);swap(tmp);return *this;}// 移动构造string(string &&s): _str(nullptr), _size(0), _capacity(0){cout << "string(string&& s) -- 移动语义" << endl;swap(s);}// 移动赋值string &operator=(string &&s){cout << "string& operator=(string&& s) -- 移动语义" << endl;swap(s);return *this;}~string(){delete[] _str;_str = nullptr;}char &operator[](size_t pos){assert(pos < _size);return _str[pos];}void reserve(size_t n){if (n > _capacity){char *tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}void push_back(char ch){if (_size >= _capacity){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}_str[_size] = ch;++_size;_str[_size] = '\0';}// string operator+=(char ch)string &operator+=(char ch){push_back(ch);return *this;}const char *c_str() const{return _str;}private:char *_str;size_t _size;size_t _capacity; // 不包含最后做标识的\0};
}

不妨先看看左值引用的应用场景:

void func1(bit::string s)
{}
void func2(const bit::string& s)
{}
int main()
{bit::string s1("hello world");// func1和func2的调用我们可以看到左值引用做参数减少了拷贝,提高效率的使用场景和价值func1(s1);func2(s1);// string operator+=(char ch) 传值返回存在深拷贝// string& operator+=(char ch) 传左值引用没有拷贝提高了效率s1 += '!';return 0;
}

问:左值引用的短板是什么?

但是当函数返回对象是一个局部变量,出了函数作用域就不存在了,就不能使用左值引用返回,只能传值返回。例如:bit::string to_string(int value)函数中可以看到,这里只能使用传值返回,传值返回会导致至少1次拷贝构造(如果是一些旧一点的编译器可能是两次拷贝构造)。

也就是说,只要是局部的对象需要返回,左值引用就是失去了作用,因为出作用域之后局部对象就会被销毁,当时候指向的就是一片位置的区域。
那么如果解决这个问题呢?

右值引用和移动语义解决上述问题:
在bit::string中增加移动构造,移动构造本质是将参数右值的资源窃取过来,占位已有,那么就不
用做深拷贝了,所以它叫做移动构造,就是窃取别人的资源来构造自己(偷梁换柱)。

来看看怎么实现

// 移动构造
string(string&& s):_str(nullptr),_size(0),_capacity(0)
{cout << "string(string&& s) -- 移动语义" << endl;swap(s);
}
不仅仅有移动构造,还有移动赋值:
在bit::string类中增加移动赋值函数,再去调用bit::to_string(1234),不过这次是将
bit::to_string(1234)返回的右值对象赋值给ret1对象,这时调用的是移动构造。
// 移动赋值
string& operator=(string&& s)
{
cout << "string& operator=(string&& s) -- 移动语义" << endl;
swap(s);
return *this;
}
int main()
{bit::string ret1;ret1 = bit::to_string(1234);return 0;
}
// 运行结果:
// string(string&& s) -- 移动语义
// string& operator=(string&& s) -- 移动语义

http://www.ppmy.cn/news/1522782.html

相关文章

探索fastFM:Python中的高效推荐系统库

文章目录 &#x1f680; 探索fastFM&#xff1a;Python中的高效推荐系统库背景&#xff1a;为何选择fastFM&#xff1f;快照&#xff1a;fastFM是什么&#xff1f;安装指南&#xff1a;如何将fastFM加入你的项目&#xff1f;快速入门&#xff1a;五个基础函数的使用实战演练&am…

C语言第二周课

目录 引言: 一、数据类型大小及分类 (1)计算机中常用存储单位 (2)整体介绍一下C语言的数据类型分类。 (3)下面是我们本节课要学的基本内容----常用的数据类型 二、 数据类型的数值范围 三、打印输出类型 数据类型打印示例: 引言: 我们常常在写C语言程序时&#xff0c;总…

滚雪球学MyBatis-Plus(13):测试与部署

前言 在上期内容中&#xff0c;我们深入探讨了 MyBatis Plus 的高级功能&#xff0c;包括自定义 SQL 注解、批量操作以及数据加密与解密。这些功能极大地提高了开发效率&#xff0c;并增强了数据操作的灵活性和安全性。 本期内容将重点介绍 MyBatis Plus 的测试与部署。我们将…

win2003_prepatched_v6b有效期到2021年4月2日,所以编译win2k3会有错误

openssl 查看证书pfx过期时间win2003_prepatched_v6b有效期到2021年4月2日&#xff0c;所以编译win2k3会有错误 要使用OpenSSL查看PFX&#xff08;也称为PKCS#12&#xff09;证书的过期时间&#xff0c;你可以使用以下命令&#xff1a; openssl pkcs12 -in your_certificate.p…

设计模式 19 观察者模式

设计模式 19 创建型模式&#xff08;5&#xff09;&#xff1a;工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式结构型模式&#xff08;7&#xff09;&#xff1a;适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式行为型模式&#xff…

自动化抢票 12306

自动化抢票 12306 1. 明确需求 明确采集的网站以及数据内容 网址: https://kyfw.12306.cn/otn/leftTicket/init数据: 车次相关信息 2. 抓包分析 通过浏览器开发者工具分析对应的数据位置 打开开发者工具 F12 或鼠标右键点击检查 刷新网页 点击下一页/下滑网页页面/点击搜…

stm32之外部flash下载算法

文章目录 下载算法下载到芯片的核心思想算法程序中擦除操作执行流程擦除操作大致流程&#xff1a;算法程序中编程操作执行流程算法程序中校验操作执行流程 创建MDK下载算法通用流程第1步&#xff0c;使用MDK提供好的程序模板第2步&#xff0c;修改工程名第3步&#xff0c;修改使…

LiveKit的agent介绍

概念 LiveKit核心概念&#xff1a; Room&#xff08;房间&#xff09;Participant&#xff08;参会人&#xff09;Track&#xff08;信息流追踪&#xff09; Agent 架构图 ​ 订阅信息流 ​ agent交互流程 客户端操作 加入房间 房间创建方式 手动 赋予用户创建房间的…

STM32(十二):DMA直接存储器存取

DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输&#xff0c;无须CPU干预&#xff0c;节省了CPU的资源。&#xff08;运行内存SRAM、程序存储器Flash、寄存器&#xff09; 12个独立可配置的通道&…

SAP自动化操作

业务场景 1、主数据维护&#xff08;物料、成本中心、科目、资产、供应商、客户等等&#xff09; 2、业务单据创建&#xff08;包括内部订单、销售订单&#xff0c;采购订单&#xff0c;生产订单&#xff0c;交货单等等&#xff09; 3、业务单据处理&#xff08;订单评审&…

HTTP 二、进阶

四、安全 1、TLS是什么 &#xff08;1&#xff09;为什么要有HTTPS ​ 简单的回答是“因为 HTTP 不安全”。由于 HTTP 天生“明文”的特点&#xff0c;整个传输过程完全透明&#xff0c;任何人都能够在链路中截获、修改或者伪造请求 / 响应报文&#xff0c;数据不具有可…

【多线程服务器】多线程下网络编程

目录 多线程模型-非阻塞IOone loop per thread one loop per thread 线程池 one loop per thread与线程池结合 目前主流多线程模型 Reactor模式线程池 Proactor模式 Master-Worker模型 多线程编程的实现 线程抢占问题 Happens-Before关系 Linux下多线程编程常用函数 …

keepalived和lvs高可用集群

keepavlied和lvs高可用集群搭建 主备模式&#xff1a; 关闭防火墙和selinux systemctl stop firewalld setenforce 0部署master负载调度服务器 zyj86 安装ipvsadm keepalived yum install -y keepalived ipvsadm修改主节点配置 vim /etc/keepalived/keepalived.conf! Conf…

C语言小游戏--贪吃蛇实现

C语言小游戏--贪吃蛇实现 1.游戏实现背景2.Win32 API介绍2.1什么是Win32 API2.2控制台程序(Console)2.3控制台屏幕的坐标COORD2.4GetStdHandle2.4.1函数语法2.4.2函数的使用 2.5GetConsoleCursorInfo2.5.1函数语法2.5.2函数的使用 2.6CONSOLE_CURSOR_INFO2.6.1结构体结构2.6.2结…

【RabbitMQ】核心概念

界⾯上的导航栏共分6部分, 这6部分分别是什么意思呢, 我们先看看RabbitMQ的工作流程 1. Producer和Consumer Producer:生产者,是RabbitMQ Server的客户端,向RabbitMQ发送消息 Consumer: 消费者,也是RabbitMQ Server的客户端,从RabbitMQ接收消息 Broker:其实就是RabbitMQSer…

UE4_地形_悬崖拉伸的解决

参考教程 【虚幻5】UE5_UE4_解决悬崖地形贴图拉伸_哔哩哔哩_bilibili 纹理处理 | 虚幻引擎 4.27 文档 | Epic Developer Community (epicgames.com) 主要通过蓝图节点解决&#xff1a;WorldAlignedTexture WorldAlignedTexture&#xff08;全局一致纹理&#xff09;函数用于…

js(vue)如何实现页面截图,向后端传递,生成PDF

利用 htmm12canvas 首先引入 npm install express multer # 或者 yarn add express multer 代码如下&#xff1a; <template><!-- <div style"width:100%;height:100%;overflow-y: scroll"><img :src"svg" style"width: 100%;&…

【H2O2|全栈】关于HTML(3)HTML基础(二)

HTML相关知识 目录 HTML相关知识 前言 准备工作 标签的具体分类&#xff08;二&#xff09; 本文中的标签在什么位置使用&#xff1f; 本期前置知识点 超文本 超文本引用和源属性 图片标签 锚链接 iframe 锚点 预告和回顾 后话 前言 本系列博客将分享HTML相关…

SprinBoot+Vue应急信息管理系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质…

docker ps -a及docker exec -it ubuntu-01 /bin/bash

docker ps -a 命令 在 Docker 中用于列出 Docker 宿主机上所有的容器&#xff0c;包括正在运行的容器和已经停止的容器。这个命令是 Docker 用户常用的命令之一&#xff0c;用于查看和管理容器。 命令解析&#xff1a; docker&#xff1a;这是 Docker 的命令行接口&#xff…