Unity常见面试题详解(持续更新...)

news2024/12/24 0:09:15

 一丶声明、定义、实例化、初始化

1、首先我们来讨论在C/C++中的声明和定义..

1)我们先从函数声明和定义说起...

一般我们在C++里都会先定义一个函数,然后再Main函数前将函数声明,比如:

//函数声明
int Add(int);


int Main
{

}
//函数定义
int Add(int)
{
}

声明就是告诉编译器,咱这儿有一个名字叫Add,返回值和参数需要int的函数,就给你说一声

定义就是在内存中拓展出了这么一片空间给该函数分配内存

所以你看,定义只能定义一次吧,如果你稍微变了个啥,这函数就不是自己了,但是声明你随意,你想声明啥声明啥,我内存没有啊,也就不存在调用,就相当于你在那空喊,没人理你...

2)我们再来讨论变量的声明和定义...

在C++里面,我们是这么声明和定义的

//声明
extren int var;
typeof int INT;
struct Node;

//定义
extern int ble = 10;

所以声明是不开辟内存空间的,而定义必须占用内存空间...

因此,在C++中,常用到定义和声明的就是函数和变量。。。

3)实例化和初始化

在面向对象的编程中,通常把用类创建对象的过程成为实例化,注意,他一般用在类上

初始化可以理解为给声明的对象赋值的过程,也就相当于定义

2:C#中的定义和声明

        在C#中,其实和C++大概一样的,不过在C#中,你定义一个函数以后,可以直接进行使用,而不用在主函数体上方声明函数,至于变量的定义和声明,和C++一样,如果是int a ;只是声明,没有定义,使用int  a = 10;这样才算创建出来了变量。


二、委托和事件

一:委托

        我说的这一点很重要,所有的代码语言创造者母语都是英语,我们从英语翻译到中文的过程中难免会存在一些不太能还原本意的词,比如我之前一直不理解构造函数和析构函数,只知道这俩货作用相反,直到我看到了它的英文意思,Construstor/Distructor,我才彻底理解了他们的作用。

        接下来我们来看委托,Delegate,来看两个例句,深入理解Delegate...

Can you delegate some tasks or projects?                                你能够分配一些任务或者项目吗?

So why not delegate more work to your employees?    所以你为啥不给你的员工多分分配点任务?

从上面的句子中我们可以看到,他就是分配,也就是委托的意思(但是感觉可能有些人对委托的理解不如分配来的直接,至少对我来说是这样)

微软官方的解释是委托可以获取一个或多个方法,但是类型和返回值必须和方法相同,可以理解成委托是方法的抽象,也就是说定义一个方法的模板,至于这个方法具体是怎么样的,就由方法自己去实现。这点和函数指针很像...后续写单播委托时候再添加这部分内容。

话不多说,看代码...

1:单播委托——一次只能装进去一个方法

Public delegate 返回值 MyDelegate(参数1,参数2)

就这么一步,我们就把委托定义出来了,接下来要做的就是把这玩意儿实例化出来,那我们怎么把我们的方法给委托呢?

第一点就是我们需要有和定义的委托类型一致的返回值和参数列表

这点比较像C语言函数指针,我们用函数指针来说明上一个问题

//使用Typedef将该函数指针声明为一种类型,它是指向两个参数为int,返回值为int的函数指针
typedef int (*Calculator)(int x , int y);

int Add(int a ,int b)
{
    return a+b;
}

int Multiply(int a ,int b)
{
    return a*b;
}

//函数指针的使用

Calculator Pointer1 = &Add;
Calculator Pointer2 = &Multiply;

//这样我们在调用函数的时候就不再写函数,而是采用函数指针的方法,间接的指向了该类型的函数
Pointer1(0,1);
Pointer2(1,2);

从上面的函数指针我们可以看出,我们在注册方法的时候,可以间接的声明一个和该方法类型和返回值都一致的指针类型,从而调用函数指针即可,那么我们的委托和它是类似的....

接下来看我们的委托的实例化和方法的插入,可以使用new,也可以直接引用方法:

//实例化委托
MyDelegate myDelegate = new MyDelegate(Function);

//简化写法
myDelegate = Telegate;



返回值类型 Function(参数1,参数2)
{
    方法体;
}

委托的调用,可以使用Invoke,也可以直接写委托名+()

可以通过Invoke进行调用委托
myDelegate.Invoke();

也可以直接myDelegate();

2:多播委托——一次装多个方法,但不安全

在上面的方法添加环节,我们只需要做小小的修改

myDelegate += ChangeColor;
myDelegate += Log;

但是其实我们没事儿也不会这么干,这样长期下来有可能会存在内存泄漏,如果顺序执行列表中方法有一个出错了,后面的就都不会执行了,所以我们还有其他更好的选择

3:Action委托和Func委托

大多数的情况下,我们不太需要自己去声明委托,而是使用现成的委托即可,C#为我们内置了两种泛型委托

1)Action委托——返回值必须为空,参数可有可无

//声明无参数的Action委托
Action action;

//声明有参数的Action委托
Action<string,float> action1;

//Action的使用
action = new Action(同参数的方法1)
action1 = new Action<string ,float> (sayhello);

//sayhello方法
public void SayHello(string name,float num)
{
    Debug.log(sting.Fromat("{0} has {1} ChampionShips .",name,num));
}

2) Func委托——返回值必须有,但是参数可有可无

//声明Func委托,前面是参数,后面是返回值
Func<double,double,double> func1;

//使用
func1 = new Func<double,double,double>(Add);


//跟Func结构一样的方法
public double Add(doublea ,double b)
{
    return a+b;
}

二:事件

事件,使对象或类具备通知能力

日常开发中,自己声明事件的机会比较少,一般是用已有事件比较多...

java中没有委托,事件这么一说,只用Interface来实现

1:五个重要因素

事件的拥有者

事件成员(Event)

事件的响应者(Event Subscriber)

事件处理器(Event handler,本质上是回调方法)

事件订阅(+=)

他们之间的关系可以如下几种:

①事件的拥有者类和事件的响应者是不同的类

using System.Timers;
using UnityEngine;

public class EventTimothyLiu1 : MonoBehaviour
{
    private void Start()
    {
        //世间间隔,每过1s就触发Elesap事件
        Timer timer = new Timer();
        timer.Interval = 1000;

        Boy boy = new();
        Girl girl = new();

        timer.Elapsed += boy.OnAction;
        timer.Elapsed += girl.OnAction;

        timer.Start();
    }
}
public class Boy
{
    internal void OnAction(object sender, ElapsedEventArgs e)
    {
        Debug.Log("1");
    }
}
public class Girl
{
    internal void OnAction(object sender, ElapsedEventArgs e)
    {
        Debug.Log("2");
    }
}

在该示例中,事件的拥有者是Timer类,事件的响应者是自定义的Boy,Girl类

所以事件的响应者和拥有者是两个类

第二个例子:

using System;
using System.Windows.Forms;

namespace EventLiu
{
    class Program
    {
        static void Main(string[] args)
        {
            //事件的拥有者:Form
            Form form = new Form();
            //事件的响应者:Controller
            Controller controller = new Controller(form);
            form.ShowDialog();
        }
    }
    class Controller
    {
        private Form form;
        /// <summary>
        /// CTOR再加Tab即可编写出构造器
        /// 也叫构造函数,每个类都必须有
        /// 在构建类的引用时自动运行的方法!
        /// </summary>
        public Controller(Form form)
        {
            if (form!= null)
            {
                //this就是类的实例
                //this后是我们定义的字段,后面是参数form
                this.form = form;
                //Click是事件
                this.form.Click += this.FormClicked;
            }
        }
        /// <summary>
        /// 事件处理器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormClicked(object sender, EventArgs e)
        {
            this.form.Text = DateTime.Now.ToString();
        }
    }
}

上述的代码段中,我们引入了Form名称空间

事件的拥有者是Form,事件的响应者是Controller

②事件的拥有者同时也是事件的响应者

using System;
using System.Windows.Forms;

namespace EventLiu
{
    class Program1
    {
        static void Main(string[] args)
        {
            //事件的拥有者:myForm
            //事件的接受者:myForm
            MyForm myForm = new MyForm();
            //事件:Click
            myForm.Click += myForm.FormClicked;
        }
    }
    /// <summary>
    /// 继承Form
    /// </summary>
    class MyForm : Form
    {
        /// <summary>
        /// 事件的处理器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        internal void FormClicked(object sender, EventArgs e)
        {
            this.Text = DateTime.Now.ToString();
        }
    }
}

事件的拥有者是Form

事件的响应者也是myForm的实例

③事件的拥有者是事件的响应者的成员(频率最高)

事件的响应者用自己的方法订阅者自己的字段成员的事件

using System;
using System.Windows.Forms;

namespace EventLiu
{
    class Program1
    {
        static void Main(string[] args)
        {
            MyForm myForm = new MyForm();
            myForm.ShowDIalog();
        }
    }
    class MyForm :Form
    {
        private TextBox textBox;
        //从订阅看事件拥有者就是button
        private Button button;

        public MyForm()
        {
            this.textBox = new TextBox();
            this.button = new Button();
            this.Controls.Add(this.button);
            this.Controls.Add(this.textBox);

            //Click是事件
            //事件的响应者是this,也就是MyForm的实例对象
            this.button.Click += this.ButtonClicked;
        }
        //事件处理器
        private void ButtonClicked(object sender, EventArgs e)
        {
            this.textBox.Text = "Hello";
        }
    }
}

在该段代码中,我们自己创建MyForm类,继承自Form

事件的拥有者是该类中的成员Button,事件的响应者是该类的实例化

也就是儿子有事件,爸爸订阅了。                                                                                                                                           

                                                                                                                                                                                                                                                                                 

④事件的响应者是事件的拥有者的成员

2:事件的完整声明格式

3:事件的简单声明格式

3:UnityEvent

4:UnityAction

5:模板方法,回调函数


三、CPU和GPU的区别

CPU和GPU从名字上来说,一个是Central Processing Unit,一个是Graphic Processing Unit

,后者是专门对图像进行处理的,为什么要针对图像处理要用专门的处理单元呢?

GPU(图形处理器)是图形系统结构的重要元件,是连接计算机和显示终端的纽带

就是说如果你要把图像显示在显示器上,必须要使用GPU,而GPU是如何工作的?可以参见下面的视频:

GPU工作原理_哔哩哔哩_bilibili

来看看CPU和GPU的内部结构

 从图中可以看出,我们GPU有大量的运算单元,而CPU只有简单的4个ALU,而我GPU有成百上千的计算单元,我们单论单线的计算能力,比如你把一个数学中的复杂运算交给CPU,效率会变得特别高,它也理所当然能够完成任务,但是在图形计算方面,我们并没有呢么多高级运算,而是要进行大量的矩阵运算变换,也就是所谓的顶点计算光栅化计算→纹理帖图→像素处理→最终输出

而在这样的运算中,都是一个一个像素点进行处理的,对于高像素的屏幕,有非常多的像素点,而对于每个像素点都得进行大量的计算,所以使用CPU效率实在太低,此时如果使用GPU,效率会变得很高,但是要注意的是:

光影都是CPU计算的,GPU只有2个工作,1多边形生成。2为多边形上颜色。

如下视频可以简单的告诉你CPU和GPU的区别...

NVIDIA现场形象展示CPU和GPU工作原理上的区别_哔哩哔哩_bilibili

这就是简单的CPU和GPU的区别介绍


四、堆和栈的区别

计算机的逻辑运算在CPU中进行,CPU中又有ALU(Arithmetic/Logic Unit)和CU(Control Unit)

ALU是由"And Gate"(与门) 和"Or Gate"(或门)构成的算术逻辑单元,主要功能是进行二位元的算术运算

而CU是负责程序的流程管理。正如工厂的物流分配部门,控制单元是整个CPU的指挥控制中心,由指令寄存器IR(Instruction Register)、指令译码器ID(Instruction Decoder)和操作控制器OC(Operation Controller)三个部件组成

问题就出在,在计算机进行计算时,并不是将所有的数据都放在CPU,而是放在内存中,CPU对其进行调用,将内存中的数据放在寄存器中,所以CPU根据计算需求对内存进行调用,而我们说的堆和栈就是在内存中的两个区域

栈内存(Stack):栈中存放的是对象的引用及对象方法中的局部变量的值(参数的值),由操作系统自动分配释放

                               栈内存是动态分配和静态分配结合,是局部的

                                入栈和出栈遵循弹夹原则,先进后出,后进先出

                                栈的生长方向向下,内存地址由高到低

堆内存(Heap):堆中存放的是实例对象及成员变量的值(属性的值),堆由开发人员分配和释放, 若开发人员不释放,程序结束时由 OS 回收

                                堆是动态分配的,是全局的

                                堆可以被看成是一棵树,如:堆排序

                                堆的生长方向向上,内存地址由低到高


五、值类型和引用类型/装箱和拆箱

值类型:C#的所有值类型均隐式派生自System.ValueType。值类型是直接存储该值的

              byte,short,int,long,float,double,decimal,char,bool 和 struct 统称为值类型。

              值类型在声明后,不管有没有赋值,都已分配了内存

引用类型:引用类型是存储该类型的引用

              string 和 class,数组,接口,委托统称为引用类型。

               引用类型在声明后,只在栈中分配一小片内存用于容纳一个地址,而此时并没有为其分配堆上的内存空间;当使用 new 创建一个类的实例时,分配堆上的空间。

装箱和拆箱:

知道了值类型和引用类型以后,就牵扯一件事,这两种类型之间需要转换,比如

ArrayList arraylist = new ArrayList();
arraylist[0].add(1);
arraylist[1].add('a');
...

此时我们需要将值类型的1和字符类型的a放在引用类型的数组中arraylist中,我们知道所有数据类型的基类是object,所以要想把值类型的对象放在引用类型的对象中,需要将值类型转换为object,这种转化是隐士进行的,此时上面的数组中的0号元素就是引用类型的

再看下一段

int a  = (int)arraylist[0];

此时我们是把上面数组中的引用类型转化为值类型int,此时就进行了强转化


六、Array/ArrayList/List

明了...


七、抽象类/接口以及区别

具体类→抽象类→接口:越来越抽象,内部实现的东西越来越少

 

1:抽象类

抽象类是未完全实现逻辑的类

抽象类为复用而生,专门用作基类

封装确定的,开放不确定的,推迟到合适的子类来实现

抽象类的成员可以是私有的,受保护的,内部的

using UnityEngine;
using System;

public class OCPandObstract : MonoBehaviour
{
    private void Start()
    {
        Vehicle1 vehicle1 = new();
        vehicle1.Run();

        //无法实例化抽象类,只能实现其子类
        Vehicle2 v = new Car2();
        v.Stop();
    }
}
/// <summary>
/// 一个汽车类,一个卡车类,里面的方法都是一样的,重新写两个类就很繁琐
/// </summary>
class Car
{
    public void Run()
    {
        Console.WriteLine("Car is running ..");
    }
    public void Stop()
    {
        Console.WriteLine("Stopped...");
    }
}
class Truck
{
    public void Run()
    {
        Console.WriteLine("Car is running ..");
    }
    public void Stop()
    {
        Console.WriteLine("Stopped...");
    }
}

/// <summary>
/// 简化方法1:使用虚函数进行重写,符合开闭原则
/// </summary>
class Vehicle1
{
    public void Stop()
    {
        Console.WriteLine("Stopped...");
    }
    public virtual void Run()
    {
        Console.WriteLine("Vehicle is running...");
    }
}
class Car1:Vehicle1
{
    public override void Run()
    {
        Console.WriteLine("Car1 is running...");
    }
}
class Truck1:Vehicle1
{
    public override void Run()
    {
        Console.WriteLine("Truck1 is running...");
    }
}

/// <summary>
/// 简化方法2:,使用抽象类,抽象函数,也就是纯虚方法
/// 此时抽象类无法实例化
/// </summary>
abstract class Vehicle2
{
    public  void Stop()
    {
        Console.WriteLine("Stopped...");
    }
    /// <summary>
    /// Run需要重写,因此作为抽象函数,没有实现部分
    /// </summary>
    public abstract void Run();
}
class Car2 : Vehicle2
{
    public override void Run()
    {
        Console.WriteLine("Car2 is running...");
    }
}
class Truck2 : Vehicle2
{
    public override void Run()
    {
        Console.WriteLine("Truck2 is running...");
    }
}

上述代码一步步介绍了为什么使用抽象类,怎么使用抽象函数

2:接口

接口是完全未实现逻辑的“类”

接口是“纯虚类”,只有成员函数,成员全部public

接口为解耦而生,高内聚,低耦合

继承自接口的类必须实现接口中的函数,且自身无法实现

接口中可以有属性,方法,事件,索引

接口成员默认是公开的,且不加任何修饰符

using UnityEngine;

public class OCPandInterface : MonoBehaviour
{
    
}
/// <summary>
/// 纯抽象类
/// </summary>
abstract class AnimalBase
{
    abstract public void Eat();
    abstract public void Sleep();
    abstract public void Walk();
}
/// <summary>
/// 抽象类,继承自纯抽象类
/// </summary>
abstract class Animal : AnimalBase
{
    public override void Eat()
    {

    }
    public override void Sleep()
    {

    }
}
/// <summary>
/// 具体类
/// </summary>
class Dog:Animal
{
    public override void Walk()
    {

    }
}
/// <summary>
/// 具体类
/// </summary>
class Duke : Animal
{
    public override void Walk()
    {

    }
}

/// <summary>
/// 引入interface,它成员变量默认为抽象且公开
/// </summary>
interface IAnimalBase
{
    void Eat();
    void Sleep();
    void Walk();
}
abstract class Animal1 : IAnimalBase
{
    /// <summary>
    /// 继承接口以后,也变成了具体方法
    /// </summary>
    public void Eat()
    {
        
    }

    public void Sleep()
    {

    }

    public abstract void Walk();
}
class Dog1 : Animal1
{
    public override void Walk()
    {

    }
}
class Duke1 : Animal1
{
    public override void Walk()
    {

    }
}

上述代码描述了如何引入的接口,且接口如何定义

3:抽象类和接口的区别


八、属性(Get访问器和Set)和字段,static关键字

首先看看C#有哪些成员

 1:字段(field)

字段是一种表示与对象或类型关联的变量,也叫成员变量

看如下代码,可以看出字段是如何一步步变成属性

using UnityEngine;
using System;

public class GetSetProperty : MonoBehaviour
{
    
    private void Start()
    {
        //一、未使用Get/Set属性
        Student stu1 = new();
        Student stu2 = new();
        Student stu3 = new();

        stu1.Age = 20;
        stu2.Age = 20;
        stu3.Age = 20;

        //此时如果有一个年龄被不小心修改了,比如第三个学生年龄修改成200,这种字段被污染很难发现
        int avgAge = (stu1.Age + stu2.Age + stu3.Age) / 3;
        //Debug.Log(avgAge);


        //二、使用Get/Set方法
        Student1 stu4 = new();
        Student1 stu5 = new();
        Student1 stu6 = new();

        //此时如果不小心将年龄修改成200,程序就会报错
        //可以使用try catch,程序就不会崩溃

        stu4.SetAge(20);
        stu5.SetAge(20);
        //stu6.SetAge(200);
        int avgAge1 = (stu4.GetAge() + stu5.GetAge() + stu6.GetAge())/3;
        try
        {
            stu6.SetAge(200);
            Debug.Log(avgAge1);
        }
        catch (Exception ex)
        {
            Debug.Log(ex.Message);
        }

        //三、使用Get/Set访问器
        Student2 stu7 = new Student2();
        Student2 stu8 = new Student2();
        Student2 stu9 = new Student2();

        stu7.Age = 20;
        stu8.Age = 20;
        stu8.Age = 20;
        int avgAge2 = (stu7.Age + stu8.Age + stu9.Age) / 3;

        Debug.Log(avgAge2);
    }
}
class Student
{
    public int Age;
    public int Score;
}

/// <summary>
/// 二、此时使用Get,Set函数,可以对字段进行约束
/// </summary>
class Student1
{
    private int age;
    public int GetAge()
    {
        return this.age;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="value"></param>
    public void SetAge(int value)
    {
        if (value >= 0 && value <= 120)
        {
            this.age = value;
        }
        else
            throw new System.Exception("value has error");
    }
}

    /// <summary>
    /// 三、使用微软的Get/Set访问器
    /// </summary>
class Student2
{
        private int age;
        public int Age
        {
            get
            {
                return age;
            }
            set
            {
                if (value >= 0 && value <= 120)
                {
                    this.age = value;
                }
                else
                {
                    throw new Exception("Age value has error");
                }
            }
        }
}

刚开始我们使用字段存储数据

但是考虑到暴露的缘故,我们引入了Get和Set函数来对字段进行约束

微软对Get/Set访问器进行了简化,就形成了Get/Set访问器

可以使用PropFull进行快速生成属性

2:属性(Prooerty)

属性是一种用于访问对象或类型的特征的成员,属性是字段的自然扩展

3:属性和字段的关系

属性和字段都是用于表示实体的状态

属性大多数情况是字段的包装器

建议:永远使用属性来暴露数据,即字段永远是private或protected的

4:static关键字

static关键字可以在类的定义,变量的声明,方法的定义中

变量前加上Static,变量成为静态变量,静态变量的内存分布在全局静态区,相当于它就是全局变量,Time.timescale就是静态变量

在函数前加上static,函数就变成了静态函数,直接类名+函数名就可以调用,比如Debug,或者Find函数都是静态函数

在类名的前面加上static,该类就变成了静态类,静态类不需要被实例化它不能继承,静态类内的成员都需要带上static关键字,但是静态函数不需要一定在静态类中

一般情况下,将工具函数或者工具类,做成静态类或者静态函数。


九、匿名方法/λ表达式的用法/LinQ用法


十、字典,队列,哈希表,Stack和Queue


十一、Unity中AB包何时使用以及如何使用


十二、Unity中的数据加载方式有几种?


13:容器/迭代器

14:射线检测,碰撞检测

15:图形学的渲染流程是什么?

16:有哪些常见的渲染算法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/384348.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

tmux终端复用软件

一、安装[rootpool-100-1-1-159 test]# yum install tmux [rootpool-100-1-1-159 test]# yum search tmux Repository extras is listed more than once in the configuration Last metadata expiration check: 0:33:52 ago on Fri 03 Mar 2023 09:10:34 AM CST.Name Exactly M…

【C++】适配器模式 -- stack/queue/dqueue

一、适配器模式 设计模式 设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结&#xff1b;Java 语言非常关注设计模式&#xff0c;而 C 并没有太关注&#xff0c;但是一些常见的设计模式我们还是要学习。 迭代器模式 其实我们在前面学习 strin…

call、apply、bind的区别以及源码实现

首先&#xff0c;需要明确&#xff0c;call()、apply()、bind()这三个方法的作用都是 改变this指向它们之间的不同点在于&#xff1a;call和apply是直接调用的&#xff0c;而bind不会立即调用&#xff0c;需要手动调用&#xff08;原因在于bind返回的是一个改变了this指向的函数…

请你喝一杯 Corretto?谈一谈 JDK 的新选择

前言如果以20年的时间为限&#xff0c;让我们选出一个影响力最大的程序语言&#xff0c;我的答案应该只有一个 – 那就是 Java。这个1995年诞生的全新的计算机语言&#xff0c;以“一次编写&#xff0c;到处运行”的跨平台特性以及面向对象、泛型编程等现代语言的特性迅速成为了…

Allegro172版本如何通过规则设置检查器件的热平衡问题

Allegro172版本如何通过规则设置检查器件的热平衡问题 在做PCB设计的时候,器件的热平衡问题是必须考虑到的一个设计要点,尤其小封装的阻容器件,热平衡问题没有考虑好,直接影响到装配的可靠性 如下图 小封装器件,一边线宽粗并且铺铜,另外一端是一根细线 Allegro172及以上…

c语言指针怎么理解 第一部分

不理解指针&#xff0c;是因为有人教错了你。 有人告诉你&#xff0c;指针是“指向”某某某的&#xff0c;那就是误导你&#xff0c;给你挖了个坑。初学者小心不要误读这“指向”二字。 第一&#xff0c;“指针”通常用于保存一个地址&#xff0c;这个地址的数据类型在定义指…

ASGCN之依存句法图的构建

文章目录前言1.理论部分1.1 依存句法理论1.2 依存句法分析1.3 依存句法的应用2. 代码实践2.1 数据集2.2 代码实现2.3 效果查看总结前言 本文首先介绍依存句法理论&#xff0c;之后通过代码实现ASGCN中的依存句法图数据的构建。 1.理论部分 1.1 依存句法理论 词与词之间存在主…

Vue3电商项目实战-购物车模块2【04-头部购物车-商品列表-本地、05-头部购物车-删除操作-本地、06-购物车页面-基础布局】

文章目录04-头部购物车-商品列表-本地05-头部购物车-删除操作-本地06-购物车页面-基础布局04-头部购物车-商品列表-本地 目的&#xff1a;根据本地存储的商品获取最新的库存价格和有效状态。 大致步骤&#xff1a; 定义获取最新信息的API定义修改购物车商品信息的mutations定义…

Mybatis工作原理及流程

1、MyBatis介绍 MyBatis是一款优秀的持久层框架,它支持自定义SQL、存储过程以及高级映射。MyBatis免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。MyBatis可以通过简单的XML或注解来配置和映射原始类型、接口和JavaPOJO(PlainOldJavaObjects,普通老式Java对象)为…

OSSFs挂载工具简介

OSSFs挂载工具 OSSFs挂载工具简介 ​ ossfs允许您在Linux系统中将对象存储OSS的存储空间&#xff08;Bucket&#xff09;挂载到本地文件系统。挂载完成后&#xff0c;您能够像操作本地文件一样操作OSS的对象&#xff08;Object&#xff09;&#xff0c;从而实现数据共享。 ​…

RT_Thread Nano 简介, 移植

官网介绍 RT_Thread Nano 1.简介 RT-Thread Nano 是一个极简版的硬实时内核&#xff0c;它是由 C 语言开发&#xff0c;采用面向对象的编程思维&#xff0c;具有良好的代码风格&#xff0c;是一款可裁剪的、抢占式实时多任务的 RTOS。其内存资源占用极小&#xff0c;功能包括…

打怪升级之MFC变量小实验

按惯例&#xff0c;这一篇文章主要还是作者读《深入浅出MFC》整理的一些笔记。不过本次还加上了一些作者自己的理解。 实验的前期准备 做实验前&#xff0c;你最好了解一下MFC的执行流程&#xff0c;从winapp到各类控件的实际变化过程&#xff0c;可以参考博主之前的笔记。 …

SOTA!目标检测开源框架YOLOv6 3.0版本来啦

近日&#xff0c;美团视觉智能部发布了 YOLOv6 3.0 版本&#xff0c;再一次将目标检测的综合性能推向新高。YOLOv6-L6 检测精度和速度超越 YOLOv7-E6E&#xff0c;取得当前实时目标检测榜单 SOTA。本文主要介绍了 YOLOv6 3.0 版本中引入的技术创新和优化&#xff0c;希望能为从…

64. 最小路径和

64. 最小路径和 给定一个包含非负整数的 m∗nm * nm∗n 网格 grid &#xff0c;请找出一条从左上角到右下角的路径&#xff0c;使得路径上的数字总和为最小。 说明&#xff1a;每次只能向下或者向右移动一步。 示例 1&#xff1a; 输入&#xff1a;grid [[1,3,1],[1,5,1],[…

Hudi的7种索引

1、Bloom Index Bloom Index (default) 使用根据记录键构建的bloom过滤器&#xff0c;也可以使用记录键范围修剪候选文件.原理为计算RecordKey的hash值然后将其存储到bitmap中&#xff0c;为避免hash冲突一般选择计算3次 HoodieKey 主键信息&#xff1a;主要包含recordKey 和p…

[ IFRS 17 ] 新准则下如何确认保险合同

本系列文章&#xff1a;[ IFRS 17 ] 针对保险新准则 IFRS 17 进行一些列文章更新。如若文中如有所疑问或者不同见解&#xff0c;欢迎留言互动交流。 注&#xff1a;本系列文章受众群体较小众&#xff0c;如若对你感到不适&#xff0c;请立刻点击右上角的 【】 本系列文章适用…

RDD持久化原理和共享变量

&#xff08;一&#xff09; RDD持久化原理 Spark中有一个非常重要的功能就是可以对RDD进行持久化。当对RDD执行持久化操作时&#xff0c;每个节点都会将自己操作的RDD的partition数据持久化到内存中&#xff0c;并且在之后对该RDD的反复使用中&#xff0c;直接使用内存中缓存…

互联网工程师 1480 道 Java 面试题及答案整理 ( 2023 年 整理版)

最近很多粉丝朋友私信我说&#xff1a;熬过了去年的寒冬却没熬过现在的内卷&#xff1b;打开 Boss 直拒一排已读不回&#xff0c;回的基本都是外包&#xff0c;薪资还给的不高&#xff0c;对技术水平要求也远超从前&#xff1b;感觉 Java 一个初中级岗位有上千人同时竞争&#…

安卓逆向_4 --- 定位关键Smali、monitor使用、log插桩、栈追踪、methodprofiling(方法分析)

1、快速定位关键 smali 代码 1.分析流程 搜索特征字符串 搜索关键api 通过方法名来判断方法的功能 2.快速定位关键代码 反编译 APK 程序&#xff0c;AndroidManifest.xml > 包名/系统版本/组件 程序的主 activity(程序入口界面) 每个…

Allegro如何画半圆形的线操作指导

Allegro如何画半圆形的线操作指导 在用Allegro设计PCB的时候,在某些应用场合会需要画半圆形,如下图 如何画半圆形,具体操作如下 点击Add点击Arc w/Radius