c++八股文

游戏客户端开发常见八股文

c++篇



前言

看到了一些关于游戏开发c++笔试、面试题,但是有题目没有答案,作为一个只会一点点c++的小菜鸡就记录一下,以下问题答案都是chatGPT回答以及百度答案
面试问题来源:游戏开发岗面试总结


一、C++内存管理常考察点

1. C++的构造函数,复制构造函数,和析构函数

  • 构造函数(Constructor):C++中的构造函数用于初始化对象的数据成员。构造函数的名称与类名相同,没有返回类型,包括参数列表和函数体。构造函数在创建对象时自动调用,并且可以重载,即可以有多个构造函数。

  • 复制构造函数(Copy Constructor):复制构造函数用于通过已有对象创建一个新对象。复制构造函数的参数是一个同类的对象引用,它用于初始化新对象的数据成员。如果没有显式定义复制构造函数,C++会自动生成一个默认的复制构造函数。复制构造函数通常使用深拷贝(deep copy)来避免浅拷贝(shallow copy)带来的问题。

  • 析构函数(Destructor):析构函数用于在对象销毁时释放资源和做一些清理工作。析构函数的名称与类名相同,前面加上一个波浪号(~)作为前缀。析构函数没有返回类型,没有参数。当对象超出作用域、被删除或程序结束时,析构函数会被自动调用。如果没有显式定义析构函数,C++会自动生成一个默认的析构函数。

代码如下(示例):

#include <iostream>

class MyClass {
   
public:
    // 默认构造函数
    MyClass() {
   
        std::cout << "Default constructor called" << std::endl;
    }

    // 带参数的构造函数
    MyClass(int value) {
   
        std::cout << "Parameterized constructor called with value: " << value << std::endl;
    }

    // 复制构造函数
    MyClass(const MyClass& other) {
   
        std::cout << "Copy constructor called" << std::endl;
    }

    // 析构函数
    ~MyClass() {
   
        std::cout << "Destructor called" << std::endl;
    }
};

int main() {
   
    MyClass obj1; // 调用默认构造函数
    MyClass obj2(10); // 调用带参数的构造函数
    MyClass obj3 = obj1; // 调用复制构造函数
    obj3 = obj2; // 调用赋值运算符(非复制构造函数)
    return 0;
}

输出结果:

Default constructor called
Parameterized constructor called with value: 10
Copy constructor called
Destructor called
Destructor called
Destructor called

2. 什么是深复制和浅复制

深复制(deep copy)和浅复制(shallow copy)是在编程中常用的两种对象复制方法。

  • 浅复制是指创建一个新的对象,新对象的属性值与原对象相同,但对象内部的引用类型数据(如数组、对象等)仍然指向原对象的引用。也就是说,浅复制只是复制了对象的引用,而不是实际的数据。因此,修改新对象的属性值可能会影响到原对象。
  • 深复制是指创建一个全新的对象,新对象的属性值和原对象相同,但是对象内部的引用类型数据也会被复制,而不是简单的引用。这意味着,深复制创建的新对象是完全独立于原对象的,对新对象的修改不会影响原对象。

简而言之,浅复制只复制对象的引用,而深复制复制对象的内容。

3.构造函数和析构函数哪个能写成虚函数,为什么

析构函数可以被写成虚函数,而构造函数不能被写成虚函数。

  • 虚函数是用于实现多态的概念,能够在运行时根据对象的实际类型来确定调用的方法。而构造函数在对象创建时被调用,此时对象的实际类型还不确定,因此无法使用虚函数。
  • 析构函数是用于释放对象占用的资源,包括内存、文件句柄等。在继承关系中,当基类指针指向派生类对象时,如果析构函数不是虚函数,那么在调用delete操作时只会调用基类的析构函数,而不会调用派生类的析构函数。这会导致派生类对象中的资源无法被正确释放,可能会造成内存泄漏等问题。因此,为了确保派生类对象的析构函数能够正确调用,通常会将基类的析构函数声明为虚函数。

总结:由于构造函数在对象创建时被调用,对象的实际类型还不确定,无法使用虚函数;而析构函数在对象销毁时被调用,对象的实际类型已经确定,可以使用虚函数实现多态。

4.C++数组,链表,二叉树的内存排列是什么样的

  • 数组的内存排列是连续的,即所有元素在内存中是相邻存储的。

  • 链表的内存排列是非连续的,每个节点包含数据和指向下一个节点的指针,节点在内存中可以分布在不同的位置。

  • 二叉树的内存排列是通过指针链接的,每个节点包含数据以及指向左右子节点的指针。

5.结构体占多大内存如何计算,类占用多大空间如何计算,空类的空间是多少,为什么

  1. 结构体的大小是由其成员变量的大小之和决定的,可以使用sizeof运算符来计算结构体的大小。
struct A {
   
	char y;		//char类型,1字节
	char* z;	//指针类型,在 32 位系统上为 4 字节,在 64 位系统上为 8 字节
	int x;		//int类型,4字节
};
cout<<sizeof(A)<<endl; 

因此,整个结构体 A 的大小为 1 + 4 + 4 = 9 字节。但是,由于内存对齐的原因,编译器会将结构体的大小调整为 12 字节,以确保每个成员的地址都能够对齐到合适的内存边界。
这里是假设
### C++ 常见面试题及答案 #### 1. C++ 和 C 的区别是什么? C++ 是一种面向对象的编程语言,在继承了 C 语言大部分特性的同时增加了许多新的功能。主要差异在于支持类和对象的概念,允许封装、继承和多态性的实现;而 C 则是一种过程化的编程语言,侧重于函数调用而非对象操作[^1]。 #### 2. STL 是什么? STL (Standard Template Library) 是 C++ 标准模板库的缩写。它提供了多种数据容器(如 vector, list)、算法(如 sort, find),以及其他工具来简化程序开发工作。通过使用这些预定义组件,开发者能够更专注于业务逻辑而不是底层细节[^2]。 #### 3. 数组与 `std::vector` 的不同之处有哪些? 两者都是用于存储一组相同类型的元素序列,但是存在几个显著的不同: - **动态大小**:数组一旦创建就不能改变尺寸,而 `std::vector` 可以根据需要自动调整容量。 - **内存管理**:对于静态分配的数组来说,程序员负责释放不再使用的空间;相比之下,当超出作用域时会自动销毁并回收资源。 - **接口方法**:除了基本索引访问外,`std::vector` 还拥有丰富的成员函数来进行插入、删除等操作,这使得它的灵活性远超传统意义上的数组。 ```cpp #include <iostream> #include <vector> int main() { int fixedArray[] = {0, 1, 2}; // 静态数组 std::vector<int> dynamicVector; dynamicVector.push_back(0); // 动态向量 dynamicVector.emplace_back(1); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值