虚幻-八股文

虚幻

虚幻架构

虚幻MVC

MVC : M数据层、V视图层、C控制、视图层驱动数据层

[浅谈UE] 我理解的Unreal MVC模式 - 哔哩哔哩 (bilibili.com)

网络

虚幻引擎服务器DS和LS区别

虚幻引擎中的DS和LS分别指代服务器(Dedicated Server)和本地服务器(Listen Server),它们在游戏开发和多人游戏中具有不同的功能和用途。

  1. Dedicated Server(DS):

    • DS是一个独立的服务器进程,专门用于处理游戏服务器的运行和管理。
    • DS通常在远程服务器上运行,由游戏开发者或托管提供商管理。
    • DS负责处理游戏逻辑、网络通信和与客户端的交互。
    • DS可以支持大规模多人游戏,因为它专注于处理游戏逻辑和网络通信,不需要同时处理图形渲染等任务。
    • DS可以在无人参与的情况下持续运行,不需要玩家的直接参与。
  2. Listen Server(LS):

    • LS是一个游戏实例,允许一个玩家作为主机同时充当服务器和客户端。
    • LS在玩家的本地计算机上运行,玩家可以在同一台计算机上启动游戏并充当服务器。
    • LS负责处理游戏逻辑、网络通信,并与其他玩家的客户端进行交互。
    • LS通常用于小规模多人游戏,例如合作游戏或局域网游戏,因为它受限于主机计算机的性能和带宽。
    • LS需要玩家的参与,一旦玩家关闭游戏或离开服务器,服务器将停止运行。

总结:DS用于大规模多人游戏,在远程服务器上运行,专注于处理游戏逻辑和网络通信;LS用于小规模多人游戏,在玩家的本地计算机上运行,玩家可同时充当服务器和客户端。选择使用DS还是LS取决于游戏的规模、性能要求和玩家的需求。

CPP

问答题

 

cpp中动态库和静态库区别

    1. 静态库

      • 静态库在编译阶段与应用程序代码链接,形成一个单独的可执行文件。
      • 所有的库代码都被嵌入到最终的可执行文件中。
      • 静态库对函数库的链接是在编译时期完成的。
      • 程序在运行时与函数库再无关联,移植方便。
      • 静态库会浪费空间和资源,因为所有相关的目标文件与涉及到的函数库被链接合成一个可执行文件。
    2. 动态库

      • 动态库在运行时与应用程序代码链接。
      • 当应用程序启动时,动态库被加载到内存,并可以被多个程序共享使用,从而减小程序的内存占用,提高系统效率。
      • 动态库的更新和维护比较方便,避免了重复编译和链接的问题。
      • 对于少量函数调用,动态库加载和解析的时间可能会超过函数的执行时间,影响程序性能。
  1. cpp中指针是不是数据结构 ? 是数据结构 , 代表是**指针类型的数据结构。

  2. cpp中定义常量使用宏还是const ? 都可以

使用 const

cpp
const int MAX_SIZE = 100;

 

优点:

  1. 类型安全const常量有类型,可以参与类型检查,避免类型错误。

  2. 作用域限定const常量遵循C++的作用域规则,限定在声明它的作用域内。

  3. 调试友好:调试时可以看到const常量的值。

  4. 更强的编译器优化:编译器能够更好地优化const常量。

缺点:

  1. 不可用于数组大小:在一些老的C++标准(如C++98/03)中,const常量不能用作数组的大小。但在C++11及以后,可以使用constexpr解决这个问题。

使用宏

 

cpp
#define MAX_SIZE 100

 

优点:

  1. 简洁:宏的语法简单,可以在预处理阶段替换。

  2. 可以用于条件编译:宏常用于条件编译,控制编译器编译不同的代码块。

缺点:

  1. 缺乏类型安全:宏只是简单的文本替换,没有类型信息,容易出错。

  2. 作用域不明确:宏在预处理阶段替换,没有作用域的概念,容易引发命名冲突。

  3. 调试困难:在调试时,宏被替换成实际的值或表达式,不易跟踪。

  4. 潜在错误:宏的替换容易引发一些难以发现的错误,尤其是宏定义中的优先级问题。

推荐使用 constexpr

在C++11及之后的标准中,推荐使用constexpr来定义编译时常量,它结合了const和宏的优点:

 

constexpr int MAX_SIZE = 100;

 

优点:

  1. 类型安全constexpr常量有类型,可以参与类型检查。

  2. 编译期常量constexpr常量在编译期就确定了值,可以用于数组大小等场景。

  3. 作用域限定constexpr常量遵循C++的作用域规则,限定在声明它的作用域内。

  4. 更强的编译器优化:编译器能够更好地优化constexpr常量。

结论

  • 对于简单的常量,使用constconstexpr

  • 对于需要在编译期确定值的常量,使用constexpr

  • 对于需要条件编译的场景,使用宏。

简单阐述下你认为运算符重载的意义

运算符重载是C++语言中的一项重要特性,它允许开发者为用户定义类型(例如类)重新定义或扩展运算符的行为。这在提高代码的可读性、可维护性和易用性方面具有重要意义。

### 运算符重载的意义

1. **增强代码可读性和直观性**:
   运算符重载允许开发者使用自然的语法来操作用户定义的类型,使代码更易读。例如,使用 `+` 运算符来实现自定义的向量加法,而不是调用函数 `add`,使得代码看起来更直观。
   Vector3D a(1, 2, 3);
   Vector3D b(4, 5, 6);
   Vector3D c = a + b;  // 使用运算符重载实现向量相加

2. **提高代码的可维护性**:
   运算符重载可以简化复杂类型的操作,使得代码更简洁、更具可维护性。例如,重载赋值运算符(`=`)可以确保对象在赋值操作时进行深拷贝,避免内存泄漏或其他潜在问题。
   class MyClass {
   public:
       MyClass& operator=(const MyClass& other) {
           if (this != &other) {
               // 进行深拷贝操作
           }
           return *this;
       }
   };

3. **支持自定义类型的标准库容器操作**:
   自定义类型通过运算符重载可以无缝地与标准库(如STL容器)一起使用。例如,重载比较运算符(`<`、`>`、`==` 等)允许自定义类型作为键使用在 `std::map` 或 `std::set` 中。
   class MyClass {
   public:
       bool operator<(const MyClass& other) const {
           return this->value < other.value;  // 假设 MyClass 有一个 value 成员变量
       }
   };
   
   std::set<MyClass> mySet;

4. **实现自定义类型的数值运算**:
   运算符重载允许对自定义类型执行数值运算,使得开发者可以实现类似于内置类型的操作。这对于数学库、物理引擎等场景尤为重要。
   class Complex {
   public:
       Complex(double r, double i) : real(r), imag(i) {}
       Complex operator+(const Complex& other) const {
           return Complex(real + other.real, imag + other.imag);
       }
   private:
       double real, imag;
   };
   
   Complex a(1.0, 2.0);
   Complex b(2.0, 3.0);
   Complex c = a + b;  // 使用运算符重载实现复数相加

### 总结

运算符重载通过提供自然且直观的接口,使自定义类型能够像内置类型一样使用。这不仅提高了代码的可读性和直观性,还增强了代码的可维护性和可扩展性。运算符重载在实现数学运算、支持标准库容器操作以及简化复杂类型的操作等方面都具有重要意义。通过合理使用运算符重载,开发者可以编写出更加简洁、清晰和高效的代码。

阐述下设计模式中单例模式的意义

设计模式中的单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一实例。单例模式的意义主要体现在以下几个方面:

  1. 资源控制:对于某些需要频繁访问的资源,如数据库连接、配置文件、线程池等,如果频繁创建和销毁这些资源,不仅效率低下,而且可能导致系统资源耗尽。通过单例模式,可以确保这些资源在系统中只有一个实例,从而避免了资源的浪费。

  2. 系统安全性:对于某些需要严格控制访问权限的类,如操作系统的任务管理器、安全服务等,使用单例模式可以确保整个系统中只有一个实例,从而避免了其他类创建这些实例的可能性,增强了系统的安全性。

  3. 实现全局唯一性功能:有些对象只需要一个实例就可以完成特定的功能,如日志记录器、配置管理器等。使用单例模式可以确保这些对象在系统中只有一个实例,从而方便地进行全局配置和管理。

  4. 减少命名冲突:在大型系统中,可能存在多个类需要访问同一个资源或对象。如果没有单例模式,这些类可能会创建自己的实例,导致命名冲突和代码混乱。使用单例模式可以确保系统中只有一个实例,从而避免了命名冲突的问题。

  5. 简化设计:在某些情况下,使用单例模式可以简化设计,使代码更加清晰和易于维护。例如,在一个需要频繁访问数据库的应用程序中,可以使用单例模式来管理数据库连接池,从而避免了在多个类中创建和管理数据库连接的复杂性。

  6. 方便测试:在测试过程中,有时需要模拟或替换某些对象的实例。通过单例模式,可以方便地替换这些对象的实例,从而方便地进行测试。

总之,单例模式的意义在于确保系统中某个类只有一个实例,并提供一个全局访问点来访问这个唯一实例。它有助于控制资源、提高系统安全性、实现全局唯一性功能、减少命名冲突、简化设计和方便测试等方面。然而,需要注意的是,过度使用单例模式可能会导致代码难以扩展和维护,因此在设计系统时应根据实际需求合理选择是否使用单例模式。

说一说你使用过得版本控制工具,描述下使用中的问题

使用过GIt和SVN , 我一般个人的项目会上传到Git , 在公司开发环境大多就用SVN 。 Git给我感觉更适合开源项目和个人项目里面的Star功能可以提高项目的知名度 , SVN的自带有一套可视化的代码管理工具 , 可以部署到本地也可以部署到云端 , 这点是我觉得比GIT好的地方 , 总之各有好处。

cpp中,友元的优点和缺点

面相对象的特性

面相对象的设计原则 六个

阐述下智能指针的实现手段和意义

说出你认识的设计模式,阐述他们的特点,不少于五个

针对接口编程的意义

数组指针和指针数组区别

指针数组加减一是否有意义?为什么?

cpp中头文件的意义

内联函数的意义

虚函数实现,虚函数表

虚继承相关知识了解(菱形继承)

指针和引用的区别

★ 相同点:

  • 都是地址的概念;指针指向一块内存,它的内容是所指内存的地址;引用是某块内存的别名。

★ 区别:

    • 指针是一个实体,而引用仅是个别名;
    • 引用使用时无需解引用(*),指针需要解引用;
    • 引用只能在定义时被初始化一次,之后不可变;指针可变;
    • 引用没有 const,指针有 const;
    • 引用不能为空,指针可以为空;
    • “sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小;
    • 指针和引用的自增(++)运算意义不一样;
    • 从内存分配上看:程序为指针变量分配内存区域,而引用不需要分配内存区域。

进程和线程的区别

共用体是什么?

C++中的多态是什么?

C++11特性列举一些

nullptr和NULL的区别

宏编写逻辑体和使用函数的区别

手写设计模式

main函数执行前后做了什么?

main函数为什么要返回数据整型

C++在普通平台的差异一般有哪些?简单说一下

结构体中添加函数,在内存中如何分配?

智能指针什么情况会造成内存泄漏 ? 智能指针循环引用

posted @ 2024-05-11 16:30  啊賢  阅读(49)  评论(0编辑  收藏  举报