当前位置: 首页 > news >正文

【C++】类和对象---需掌握的功能

目录

  • 1.初始化列表
    • 1.1构造函数赋值
    • 1.2初始化列表
      • 格式:
      • 编译器执行的顺序:
      • 特性:
    • 1.3explicit关键字
      • 类型替换过程
      • 多参数构造函数类型替换(C++11)
  • 2.static成员
    • 编程题
  • 3.匿名对象
  • 4.友元
    • 4.1友元函数
    • 4.2友元类
  • 5.内部类
  • 6.拷贝对象时的一些编译器优化
    • 6.1传值传参
    • 6.2传值返回
  • 7.理解类和对象

1.初始化列表

1.1构造函数赋值

创建对象时,编译器会调用构造函数来为对象中的成员变量一个合适的初始值。

但不是所有的成员变量都可以在构造函数内获得初始值的,如下代码:

在这里插入图片描述
运行后给出如下错误

在这里插入图片描述

这是因为被const修饰的变量只能在定义的时候初始化,那哪里是成员变量定义的地方?

答:成员变量在初始化列表 中定义并初始化。

如下图,是我们经常写的类:

在这里插入图片描述
在类内private访问限定符下的成员变量只是成员变量的声明 ,在对象创建时(也叫定义对象)会调用类内的构造函数(默认构造函数或非默认构造函数),其中在 成员变量的定义 的位置,也叫做初始化列表 (下面会讲,现在知道这个位置即可),成员变量在这个地方定义的,如果成员变量中有被const修饰的可以在此处初始化。

了解了这些,我们在来看一下初始化列表的具体特性和功能。

1.2初始化列表

格式:

初始化列表:在构造函数(默认构造函数或非默认构造函数)下以一个冒号开始 ,接着是一个以 逗号分隔的数据成员列表 ,每个“成员变量 ”后面跟一个放在括号中的初始值或表达式

class Date
{
public:Date():_year(1),_month(1),_day(1){}
private:int _year;int _month;int _day;
};

编译器执行的顺序:

  1. 之所以在这个位置以该格式写的代码被称为初始化列表,一是因为在这里成员变量完成定义,其次是编译器在对象创建后调用构造函数也是先执行初始化列表 ,将对应的成员变量初始化后,在执行构造函数体内的代码

    如下图:

    在这里插入图片描述

  2. 如果我们没有实现初始化链表,编译器会默认实现,因为对于成员变量必须要定义,而初始化列表就是定义成员变量的,只是这样初始化后的成员变量值为随机值,需要看它的构造函数或其他函数是否为其赋值。

    但要注意,我们没有实现初始化列表,遇到被const修饰的成员函数或其他特殊的情况(下面会讲),可就运行不了了。

    结论: 尽量使用初始化列表。

  3. 成员变量 在类中声明次序 就是其初始化列表中的初始化顺序 ,与其在初始化列表中的先后次序无关。

    如下图,调换初始化列表的顺序,可以观察到,程序的执行顺序为_year_month_day与声明顺序相同。

    在这里插入图片描述

特性:

  1. 每个成员变量在初始化列表中只能出现一次

    初始化只能初始化一次,第二次就成复制了,赋值是在构造函数体内完成。

  2. 类中如果包含以下成员,必须放在初始化列表位置处初始化。

    • 引用成员变量

      引用的特点就是在定义时必须赋值。

    • const成员变量

      被const修饰的变量,如果不在定义时初始化,其他时候无法改变它的值,那该变量的存在就没有价值。

    • 自定义类型成员(且该类中没有默认构造函数时)

      没有默认构造函数,意味着有非默认构造函数,编译器无法在其定义时自动初始化该成员变量,只能通过我们自己传值调用其非默认构造函数。

    class A
    {
    public:A(int a): _a(a){}
    private:int _a;
    };class B
    {
    public:B(int a, int ref): _Aobj(a), _ref(ref), _n(1){}
    private:A _Aobj;        //没有默认构造函数int& _ref;      //引用const int _n;   //const
    };
    
  3. 注意: 尽量使用初始化列表,如果不能用初始化列表初始化的成员变量,如需要开辟空间的情况等等,在构造函数体内完成即可,不要只盯着初始化列表。

拓展:

C++11中规定内置类型成员变量在类中声明时可以给默认值。

这里的默认值是缺省值,不是初始化,比方说对于被const修饰的成员变量,如果在声明时给出默认值,并在初始化列表初始化,最后以初始化列表为主,若是初始化列表没有初始化则以默认值为主

class Date
{
public:Date(): _year(1){cout << _year << endl;}
private:const int _year;int _month;int _day;
};
class A
{
public:A(){cout << _year << endl;}
private:const int _year = 2;
};int main()
{Date today;A a;return 0;
}

在这里插入图片描述

1.3explicit关键字

构造函数不仅可以构造与初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值的构造函数(统称:单参数默认构造函数),还具有类型替换的作用。

若不想实现这种功能,在构造函数前增加关键字explicit即可

在这里插入图片描述

类型替换过程

接下来我们一步步探索这个现象

我们先来看如下代码

int main()
{int a = 1;double b = a; //隐式类型转化return 0;
}

这个代码是可以运行成功的,变量a在为b赋值时,发生隐式类型转化,首先生成了一个const double类型的临时变量(临时变量有常性 ),变量a将值赋给这个临时变量,由临时变量将值赋给变量b

在这里插入图片描述

了解了临时变量的存在,在来看下面的一段代码

class A
{
public:A(int a): _a(a){cout << "A(int a)" << endl;}private:int _a;
};int main()
{const A& b = 1;return 0;
}

在这里插入图片描述

我们看到,代码成功运行并输出,而想要为引用初始化,需要为其赋一个同类型的变量,所以const A& b = 1;中,先创建一个临时的A类型对象(临时的对象也有常性,所以引用需要使用const修饰),并使用1为其成员变量赋值,这个过程调用构造函数,接着使对象b成为零时对象的引用,证明这么做必然会产生一个临时的变量。

在这里插入图片描述

到这里类型替换的过程也就呼之欲出了,不过结果可能和大家想象的不一样。

看如下代码

class A
{
public:A(int a): _a(a){cout << "A(int a)" << endl;}A(const A& aa): _a(aa._a){cout << "A(const A& a)" << endl;}
private:int _a;
};int main()
{A a = 1;//等价于: A a(1);return 0;
}

在这里插入图片描述

按照正常的想法,通过构造函数创建一个临时对象,在通过拷贝构造函数创建对象a,而现在只调用了构造函数,这是为什么?

这是编译器帮我们做出的优化,正常的过程是构造->拷贝 = a,但C++觉得这么做有些繁琐,便取消了拷贝的过程,直接通过1来构造对象a ,等价于A a(1)

在这里插入图片描述

  • 在C++发展之初这些优化是没有的,但随着发展,编译器不断进化,开始减少很多没必要的步骤,慢慢做出优化,同时对语法的要求更高,保证优化后对编译没有影响。
  • 一般新一点的编译器会有优化,老的编译器没有。

多参数构造函数类型替换(C++11)

对于多参数的构造函数,C++98是不支持进行类型替换的,但在C++11对这一块进行拓展,支持其多参数进行这一操作。需在进行多参数替换时,使用大括号包含需要传的参数即可。如下

在这里插入图片描述

  • 注意:若不想进行替换操作,在构造函数前增加explicit关键字即可

2.static成员

声明为static的类成员 称为 类的静态成员 ,用static 修饰的 成员变量 ,称之为 静态成员变量 ;用 static修饰成员函数 ,称之为 静态成员函数静态成员变量一定要在类外进行初始化。

其特性如下:

  1. 静态成员所有类对象共享 ,不属于某个具体的对象,存放在静态区
  2. 静态成员变量 必须在类外定义,定义时不添加static关键字,类中只是声明
  3. 类静态成员即用 类名::静态成员 或者 对象.静态成员 来访问
  4. 静态成员函数 没有 隐藏的 this指针,不能访问非静态成员
  5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制

了解了特性我们需要注意以下几种情况:

  1. 创建类的指针对象,设置为空,它可以访问类中的静态成员和静态函数

    class A
    {
    public:static void Print(){cout << _a << endl;}
    private:static int _a;
    };int A::_a = 0;int main()
    {A* a = nullptr;a->Print();return 0;
    }
    

    在这里插入图片描述

    静态成员为所有类对象共享,使用空指针调用,不涉及指针自生,甚至在静态成员函数内不会有this指针,不会造成编译错误。

  2. 静态成员函数不能调用非静态成员函数

    静态成员函数内没有this指针,无法调用除静态成员外的其他成员

  3. 非静态成员函数可以调用类的静态成员函数

    静态成员是所有类对象共享,所有对象都可以调用,非静态成员内有this指针,为类对象指针,可以调用静态成员,甚至非成员函数,普通函数或其他类的成员函数都可以通过类名::静态成员的方法调用一个类的静态成员

了解了这些,我们使用静态成员来做一道编程题:

编程题

求1+2+3+…+n_

描述:

求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句

(A?B:C)。

数据范围: 0<<n≤200
进阶: 空间复杂度 O(1) ,时间复杂度 O(n)

示例1

输入: 5

返回值:15

示例2

输入:1

返回值:1

思路:

我们创建一个类,设置两个静态成员变量,一个sum存放所有数相加的和,一个i表示当前需要加几,编写其构造函数,使创建一次对象sum加一次i,同时使i自加1,之后创建n个这个类的对象,最后得到的sum就是总和,因为成员变量一般放在private限定符下,所以在通过创建一个静态成员函数来返回这个静态成员变量sum。

注意: 创建n个对象可以使用变长数组 类名 arr[n]new,变长数组是c99中定义的,是否可以使用取决于编译器是否支持,在牛客网中的编译器支持这一语法。

代码:

class Sum
{
public:Sum(){_sum += _i;_i++;}static int Print(){return _sum;}
private:static int _sum;static int _i;
};int Sum::_sum = 0;
int Sum::_i = 1;class Solution {
public:int Sum_Solution(int n) {Sum arr[n];return Sum::Print();}
};

3.匿名对象

我们创建对象还可以通过类名() 的方式创建,这样的对象叫匿名对象声明周期 只有被创建的哪一行,该行执行完,对应的匿名对象就会被销毁。

class A
{
public:A(){cout << "A()" << endl;}A(int a, int b): _a(a), _b(b){cout << "A(int a, int b)" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;int _b;
};int main()
{A();     //匿名对象A(1, 2); //匿名对象return 0;
}

在这里插入图片描述

使用场景:

如果我们需要创建对象,但对象创建后只使用一次,那就可以用匿名对象

注意:

匿名对象具有常性 ,需要使用引用接收匿名对象时需要使用const修饰。

4.友元

友元提供了一种突破封装的方法,有时提供便利,但友元会增加耦合度,破坏了封装,所以友元不宜多用。

友元分为:友元函数友元类

4.1友元函数

友元函数定义在类外部的普通函数 ,不属于任何类,但需要在类的内部声明,声明时需要加friend 关键字。友元函数 可以 直接访问 类的私有 成员。

特性:

  • 友元函数 内类对象可访问类的私有和保护成员,但它不是类的成员函数
  • 友元函数不能用const修饰
  • 友元函数 可以在类定义的任何地方声明,不受类访问限定符限制
  • 一个函数可以是多个类的友元函数
  • 友元函数的调用与普通函数的调用原理相同
class A
{
public:friend void test(A& a); //友元函数的声明A(int a,int b):_a(a),_b(b){}
private:int _a;int _b;
};void test(A& a)
{cout << a._a << endl;
}int main()
{A a(1, 2);test(a);return 0;
}

在这里插入图片描述

4.2友元类

友元类所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。

注意:

  1. 友元关系是单向的,不具有交换性。

    在这里插入图片描述

  2. 友元关系不能传递

    如果A是B的友元,B是C的友元,则不能说明A是B的友元

    如果A是B的友元,C也是B的友元,也不能说明A和B一个是另一个的友元。

    在这里插入图片描述

  3. 友元关系不能继承

class A
{
public:friend class B;//友元类的声明A(): _Aa(1), _Ab(2){}private:int _Aa;int _Ab;
};class B
{
public:B(): _Ba(1), _Bb(2){A aa;cout << aa._Aa << " " << aa._Ab << " " << endl;}private:int _Ba;int _Bb;
};int main()
{B bb;return 0;
}

在这里插入图片描述

5.内部类

如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。

class A
{
public:A(): _Aa(1), _Ab(2){}class B{public:B(): _Ba(1), _Bb(2){A aa;cout << aa._Aa << " " << aa._Ab << " " << endl;}private:int _Ba;int _Bb;};private:int _Aa;int _Ab;static int _Ac;
};

特性:

  1. 内部类就是外部类的友元,内部类可以通过外部类的对象参数来访问外部类中的所有成员,但外部类不是内部类的友元。

  2. 内部类可以定义在外部类的public、protected、private都是可以的

  3. 想要创建一个内部类对象,需要通过外部类指定

    int main()
    {A::B bb;//创建内部类return 0;
    }
    

    在这里插入图片描述

  4. 注意内部类可以直接访问外部类中的static成员,不需要外部里的对象/类名。

    注意:友元类不可以直接访问static成员

  5. sizeof(外部类) = 外部类,和内部类没有任何关系。

    int main()
    {cout << sizeof(A) << endl;return 0;
    }
    

    在这里插入图片描述

  • 对于内部类,我们只做了解就好,在C++中很少用到内部类,而java中内部类用的倒是很多。

6.拷贝对象时的一些编译器优化

在传参和传返回值的过程中,一般编译器会做出一些优化,减少对象的拷贝,这个在一些场景下可以帮我们提高程序的运行速率。

创建如下类,通过下面这个类创建的对象进行操作,观察现象,搞清楚编译器的优化

class A
{
public:A(int aa = 0):_a(aa){cout << "A()" << endl;}~A(){cout << "~A" << endl;}A(const A& aa):_a(aa._a){cout << "A(const A& a)" << endl;}A& operator=(const A& aa){if (&aa != this){_a = aa._a;}cout << "A& operator=(const A& a)" << endl;return *this;}
private:int _a;
};

在上面讲explicit关键字时,我们已经知道了类型替换的概念,知道编译器会优化一些步骤使之更加便捷,下面我们针对这一现象再来研究一下

6.1传值传参

void test1(A aa)
{}void test3(const A& aa)
{}int main()
{A aa1;//构造test1(aa1);//拷贝构造cout << "-----------------" << endl;test3(aa1);//引用传参,对象已存在无需进行构造或拷贝cout << "-----------------" << endl;test1(A(1));//匿名对象构造+拷贝构造 -> 优化为直接构造cout << "-----------------" << endl;test1(1);//隐式类型,构造+拷贝构造 -> 优化为直接构造return 0;
}

在这里插入图片描述

对于正常的创建对象,之后将对象传递给参数,这样的操作,虽然也进行了构造和拷贝两个步骤,但它是在两行上分别执行的,绝大多数编译器都不会在此处进行优化。(一些比较激进的编译器会这样做)

对于引用传参,因为对象已经创建好了,直接引用即可,只执行了一个构造,而且函数执行完后还可以接着使用,但注意,若传过去的对象不会改变,建议使用const修饰,防止发生变化。

对于使用匿名对象传参隐式类型替换 为对象的操作,正常来看都需要经过构造、拷贝两个步骤,形参才会被赋予数据,而经过编译器优化后省去了拷贝的步骤,直接使用初始化的值构造形参。但对象在函数执行完后就无法在使用。

6.2传值返回

A test2()
{A a;return a;
}A test4()
{return A(1);
}int main()
{test2();//构造+拷贝构造cout << "-----------------" << endl;A aa2 = test2();//构造+拷贝构造+拷贝构造 -> 优化为:构造 + 拷贝构造cout << "-----------------" << endl;A aa1;//构造aa1 = test2();//构造+拷贝构造+赋值重载cout << "-----------------" << endl;A aa3 = test4();//使用匿名对象返回,构造+拷贝+拷贝 -> 构造cout << "-----------------" << endl;return 0;
}

在这里插入图片描述

对于传值返回中的第16行代码,返回值由一个未定义的对象接收,意味着以返回对象为参数,调用拷贝构造函数,定义该对象,所以该行代码的执行步骤应该为:构造、拷贝、拷贝编译器对其进行优化,将原本test2中返回时需要拷贝出一个临时对象的操作,优化为直接拷贝出所接收的对象,将两个拷贝优化为一个拷贝。

在这里插入图片描述

对于第19行,因为对象以及定义,使用定义好的对象接收返回对象,这里就是赋值重载,对于赋值重载无法进行优化。

对于21行,接收匿名函数返回的对象,原本应该是匿名对象调用构造函数创建对象,之后拷贝一个临时对象,由临时对象在经过拷贝创建出所要的对象,经过编译器优化,两次拷贝都不在调用,因为匿名对象只执行一行,对象返回后就会被销毁,编译器直接使用匿名对象构造出的对象作为接收返回值的对象,所得结果相同,但过程更为简洁。

在这里插入图片描述

总结:

  • 对象传参

    尽量使用引用接收参数

  • 对象返回

    1. 接收返回值对象,尽量使用拷贝方法接收,不要使用赋值接收
    2. 函数中返回对象时,尽量返回匿名对象。

7.理解类和对象

对于现实生活中的实体,计算机是不认识的,计算机只认识二进制格式的数据。如果想要让计算机认识现实生活中的实体,用户必须通过某种面向对象的语言,对实体进行描述,然后通过编写程序,创建对象后计算机才可以认识。

比如说我们使用的手机实体,想要认识让计算机认识手机,需要经过以下步骤:

  1. 先对现实生活中手机实体进行抽象—即在人为思想层面对手机进行认识,手机有什么属性,有那些功能,即对手机进行抽象认知的一个过程。
  2. 经过1后,在人的头脑中已经对手机有了一个清醒的认识,只不过此时计算机还不清楚,想要让计算机识别人想象中的手机,就需要人通过某种面向对象的语言(如:Java、C++、Python等)将手机用类来进行描述,并输入到计算机中。
  3. 经过2后,在计算机中就有了一个手机类,但手机类只是站在计算机的角度对手机对象进行描述的,通过手机类,可以实例化出一个个具体的手机对象,此时计算机才能知道手机是什么东西。
  4. 此时用户就可以借助计算机中手机对象,来模拟现实中的手机实体了。

在类和对象阶段,大家一定要体会到:

类是对某一类实体(对象)来进行描述的,描述该对象具有那些属性,那些方法,描述完成后就形成了一种新的自定义类型,用该自定义类型就可以实例化具体的对象。

在这里插入图片描述

相关文章:

【C++】类和对象---需掌握的功能

目录1.初始化列表1.1构造函数赋值1.2初始化列表格式&#xff1a;编译器执行的顺序&#xff1a;特性&#xff1a;1.3explicit关键字类型替换过程多参数构造函数类型替换&#xff08;C11&#xff09;2.static成员编程题3.匿名对象4.友元4.1友元函数4.2友元类5.内部类6.拷贝对象时…...

2.12、进程互斥的软件实现方法

学习提示: 理解各个算法的思想、原理结合上小节学习的 “实现互斥的四个逻辑部分”&#xff0c;重点理解各算法在进入区、退出区都做了什么分析各算法存在的缺陷&#xff08;结合 “实现互斥要遵循的四个原则” 进行分析&#xff09; 1、单标志法 算法思想&#xff1a;两个进…...

Java面试题-数据库

数据库相关 MySQL的索引使用 默认会有主键索引。 索引分类&#xff1a;单值索引、复合索引、唯一索引 详细文章 MySQL explain 分析 MySQL通过explain关键字分析SQL的执行计划。&#xff08;Oracle通过EXPLAIN PLAN FOR sql&#xff09; IDSELECT_TYPETABLEPARTITIONSTYPEPOSS…...

select 与 where、group by、order by、limit 子句执行优先级比较

当 select 和 其他三种语句的一者或者多者同时出现时&#xff0c;他们之间是存在执行先后顺序的。 他们的优先级顺序是&#xff1a;where > group by > select > order by > limit 目录 1、select 与 where 2、group by 与 where 、select 2、select 与 order…...

【Docker】用开源umami监控你的站点访问量

新年到&#xff0c;祝大家兔年吉祥&#xff01;&#x1f389; 1.介绍 umami是一个开源的站点访问量监看程序&#xff0c;其支持docker部署到自己的服务器上。相比较百度等收费的网站信息监看&#xff0c;这种方式对于小站长来说更加实惠一些 2.docker安装的坑 2.1 docker-co…...

java环境配置

java环境配置步骤下载jdk安装jdk配置环境变量通过控制台命令验证配置是否成功大功告成安装教程&#xff1a; https://blog.csdn.net/m0_37220730/article/details/103585266 下载jdk 若不理解JDK/JRE/JVM的关系&#xff0c;可以点此查看初识Java&#xff08;概念、版本迭代、…...

Linux系统服务:Apache安装及配置应用

目录 一、Apache安装 1、Apache简介 2、Yum安装 3、编译安装 4、服务管理 5、编译安装实现systemctl服务管理 二、Apache配置应用 1、基础应用 2、隐藏版本号 3、更改监听端口 一、Apache安装 1、Apache简介 Apache即阿帕奇是一款开源的、世界使用排名第一的Web服务…...

动态规划(Dynamic Programming)——背包问题

动态规划(Dynamic Programming) 背包问题 目录动态规划(Dynamic Programming)背包问题01背包问题输入格式输出格式数据范围输入样例输出样例&#xff1a;二维一维完全背包问题多重背包问题输入格式输出格式数据范围输入样例输出样例&#xff1a;数据范围二进制优化分组背包问题…...

JVM学习02:内存结构

JVM学习02&#xff1a;内存结构 1. 程序计数器 1.1、定义 Program Counter Register 程序计数器&#xff08;寄存器&#xff09; 作用&#xff1a;是记住下一条jvm指令的执行地址 特点&#xff1a; 是线程私有的不会存在内存溢出 1.2、作用 程序计数器物理上是由寄存器来实…...

6年软件测试经验,从我自己的角度理解自动化测试

接触了不少同行&#xff0c;由于他们之前一直做手工测试&#xff0c;现在很迫切希望做自动化测试&#xff0c;其中不乏工作5年以上的人。 本人从事软件自动化测试已经近6年&#xff0c;从server端到web端&#xff0c;从API到mobile&#xff0c;切身体会到自动化带来的好处与痛楚…...

三种方式查看linux终端terminal是否可以访问外网ping,curl,wget

方法1&#xff1a;ping注意不要用ping www.google.com.hk来验证&#xff0c;因为有墙&#xff0c;墙阻止了你接受网址发回的响应数据。即使你那啥过&#xff0c;浏览器都可以访问Google&#xff0c;terminal里面也是无法得到响应 百度在墙内&#xff0c;所以可以正常拿到响应信…...

【Call for papers】SIGCOMM-2023(CCF-A/计算机网络/2023年2月15日截稿)

ACM SIGCOMM is the flagship annual conference of the ACM Special Interest Group on Data Communication (SIGCOMM). ACM SIGCOMM 2023, the 37th edition of the conference series, will be held in New York City, US, September 10 - 14, 2023. 文章目录1.会议信息2.时…...

Chapter5:机器人感知

ROS1{\rm ROS1}ROS1的基础及应用&#xff0c;基于古月的课&#xff0c;各位可以去看&#xff0c;基于hawkbot{\rm hawkbot}hawkbot机器人进行实际操作。 ROS{\rm ROS}ROS版本&#xff1a;ROS1{\rm ROS1}ROS1的Melodic{\rm Melodic}Melodic&#xff1b;实际机器人&#xff1a;Ha…...

[acwing周赛复盘] 第 90 场周赛20230211 补

[acwing周赛复盘] 第 90 场周赛20230211 补 一、本周周赛总结二、 4806. 首字母大写1. 题目描述2. 思路分析3. 代码实现三、4807. 找数字1. 题目描述2. 思路分析3. 代码实现四、4808. 构造字符串1. 题目描述2. 思路分析3. 代码实现六、参考链接一、本周周赛总结 T1 模拟T2 模拟…...

数组

一、数组中重复的数字题目描述&#xff1a;在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的&#xff0c;但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如&#xff0c;如果输入长度为7的数组{2,3,1…...

MicroBlaze系列教程(4):AXI_UARTLITE的使用

文章目录 @[toc]AXI_UARTLITE简介MicroBlaze添加串口IP常用函数使用示例参考资料工程下载本文是Xilinx MicroBlaze系列教程的第4篇文章。 AXI_UARTLITE简介 axi_uartlite是Xilinx提供axi-lite接口的通用串口IP核,用AXI-Lite总线接口和用户进行交互,速度可以根据不同的芯片调…...

GO 中的 init 函数

前言 go 语言中有一个非常神奇的函数 init ,它可以在所有程序执行开始前被执行&#xff0c;并且每个 package 下面可以存在多个 init 函数&#xff0c;我们一起来看看这个奇怪的 init 函数。 init 特性 init 函数在 main 函数之前执行&#xff0c;并且是自动执行&#xff1b…...

使用C#编写k8s CRD Controller

本文项目地址&#xff1a;k8s-crd - Repos (azure.com)CRDCRD指的是Custom Resource Definition。开发者更多的关注k8s对于容器的编排与调度&#xff0c;这也是k8s最初惊艳开发者的地方。而k8s最具价值的地方是它提供了一套标准化、跨厂商的 API、结构和语义。k8s将它拥有的一切…...

Ansible---playbook剧本

目录 引言&#xff1a;什么是playbook&#xff1f; 一、Playbook 1.1、playbook中的核心元素 1.2、playbook中的基础组件 1.3、playbook格式说明 1.4、实例&#xff1a;httpd服务剧本 二、playbook中的模块 2.1、Templates 模块 2.2、tags 模块 2.3、Roles 模块 引言&…...

Delphi 中TImageCollection和TVirtualImageList 控件实现high-DPI

一、概述RAD Studio允许你通过使用TImageCollection组件和TVirtualImageList组件&#xff0c;在你的Windows VCL应用程序中包含缩放、高DPI、多分辨率的图像。这两个组件位于Windows 10面板中&#xff1a;注意&#xff1a;如果你使用FireMonkey进行跨平台应用&#xff0c;请看T…...

Ros中如何给UR5配置自定义工具 | 在Rviz中给UR5机器人装载定义工具 | UR5配置自定义末端执行器

前言 在学习和项目研究的过程中&#xff0c;我需要在Ur5e上装上工具&#xff0c;以对现实场景进行仿真。网上会有一些装载/配置现成的夹爪&#xff0c;例如Robotiq等。但和我们装载自定义工具的场景还有些差异&#xff0c;因此写一篇博客记录&#xff0c;可能有偏差。如果有问…...

数据库 delete 表数据后,磁盘空间为什么还是被一直占用?

插&#xff1a; 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家一起学习鸭~~~ 最近有个上位机获取下位机上报数据的项目&#xff0c…...

docker-微服务篇

docker学习笔记1.docker简介1.1为什么会出现docker&#xff1f;1.2docker理念1.3虚拟机&#xff08;virtual machine&#xff09;1.4容器虚拟化技术1.5一次构建到处运行2.docker安装2.1前提条件2.2docker基本构成2.3docker安装步骤*2.4测试镜像3.docker常用命令3.1 启动docker3…...

图像优化篇

目录&#xff08;1&#xff09;矢量图&#xff08;2&#xff09;位图 2.1 分辨率2&#xff0c;图像格式格式选择建议&#xff1a;&#xff08;1&#xff09;矢量图 被定义为一个对象&#xff0c;包括颜色&#xff0c;大小&#xff0c;形状&#xff0c;以及屏幕位置等属性&…...

在surface go 2上安装ubuntu 20.04

在surface go 2上安装ubuntu 20.04 1.制作安装盘 下载ubuntu系统的iso文件 使用Rufus软件将u盘制作为ubuntu系统的安装盘 2.在surface go 2上操作 禁用快速启动 在 Windows 中&#xff0c;禁用“电源选项”中的“快速启动”>选择电源按钮的功能 禁用 Bitlocker 在 Wi…...

Java:SpringMVC的使用(1)

目录第一章、SpringMVC基本了解1.1 概述1.2 SpringMVC处理请求原理简图第二章、SpringMVC搭建框架1、搭建SpringMVC框架1.1 创建工程【web工程】1.2 导入jar包1.3 编写配置文件(1) web.xml注册DispatcherServlet(2) springmvc.xml(3) index.html1.4 编写请求处理器【Controller…...

自动化测试岗位求职简历编写规范+注意事项,让你的简历脱颖而出

目录 前言 1.个人信息 2.教育背景(写最高学历) 3.个人技能(按精通/掌握/熟练/了解层次来写) 4.工作经历 5.工作经验/项目经历 6.自我评价 总结 前言 挑选一个阅读舒适度不错的模板 HR和面试官看的简历多&#xff0c;都是快速阅读&#xff0c;舒适度特别重要&#xff1b…...

C 字符串

在 C 语言中&#xff0c;字符串实际上是使用空字符 \0 结尾的一维字符数组。因此&#xff0c;\0 是用于标记字符串的结束。空字符&#xff08;Null character&#xff09;又称结束符&#xff0c;缩写 NUL&#xff0c;是一个数值为 0 的控制字符&#xff0c;\0 是转义字符&#…...

【每日一题Day115】LC2335装满杯子需要的最短总时长 | 贪心

装满杯子需要的最短总时长【LC2335】 You have a water dispenser that can dispense cold, warm, and hot water. Every second, you can either fill up 2 cups with different types of water, or 1 cup of any type of water. You are given a 0-indexed integer array amo…...

Flink流计算处理-旁路输出

使用Flink做流数据处理时&#xff0c;除了主流数据输出&#xff0c;还自定义侧流输出即旁路输出&#xff0c;以实现灵活的数据拆分。 定义旁路输出标签 首先需要定义一个OutputTag&#xff0c;代码如下&#xff1a; // 这需要是一个匿名的内部类&#xff0c;以便我们分析类型…...