> 文章列表 > c++华为od面经

c++华为od面经

c++华为od面经

手撕代码:

力扣1004 最大连续1的个数 给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1
的最大个数 。 输入:nums = [1,1,1,0,0,0,1,1,1,1,0], K = 2 输出:6
解释:[1,1,1,0,0,1,1,1,1,1,1] 翻转后最长的子数组长度为 6。

c++为什么要虚析构?

C++要求程序员手动管理内存,包括对象的构造和销毁。当一个类中含有虚函数时,其析构函数应该也是虚函数,这样在删除基类指针指向的派生类对象时,可以正确调用派生类的析构函数。如果析构函数不是虚函数,那么只会调用基类的析构函数,就无法释放掉派生类的资源,会导致内存泄漏等问题。

为什么不虚构造?

C++中的构造函数不需要虚函数,因为在创建一个对象时,只有当前正在创建的类的构造函数会被调用,因此不存在多态性。同时,在构造函数中调用虚函数会导致一些问题,例如派生类的成员变量还没有被初始化,就会调用派生类的虚函数,这可能导致程序崩溃或者行为不可预测。

说说快排和冒泡

快排采用分治思想,将一个数组分成两个子数组,然后递归地排序两个子数组。具体实现中,选择一个基准元素,将数组中小于等于它的元素放在它的左边,大于它的元素放在右边,最后再递归地对左右子数组进行快排。
冒泡排序则是通过不断地交换相邻的元素来实现排序的。具体实现中,从数组的第一个元素开始,不断比较它与下一个元素的大小关系,如果前者大于后者,则交换它们的位置。重复这个过程,直到整个数组有序为止。

c++三大特性?

面向对象编程:C++支持封装、继承和多态等OOP特性,让开发者可以更加方便地组织代码,提高代码重用性和可维护性。
泛型编程:C++支持泛型编程,即通过模板来实现对不同数据类型的通用处理。这使得程序可以更加灵活和易于扩展,同时也提高了代码的复用性。
内存管理:C++中需要手动管理内存,这既是其优点之一,也是缺点之一。手动管理内存使程序员可以更好地掌控内存分配和释放操作,而且避免了由于自动垃圾回收带来的不确定性和性能问题,但同时也需要开发者具备一定的内存管理经验和技巧。

说说多态

静态多态:也称为函数重载,即在同一作用域内定义了多个名称相同但参数类型、个数或顺序不同的函数。在调用这些函数时,编译器会根据实参的类型和数量自动匹配合适的函数进行调用。

动态多态:也称为虚函数,即通过将基类函数声明为虚函数,实现在派生类中重写基类函数的功能。在运行时,如果指向派生类对象的基类指针调用该函数,则会根据指向的派生类类型选择正确的函数执行。

说说虚函数

通过将基类的成员函数声明为虚函数,可以在派生类中重新定义该函数以实现特定的功能。
实现动态多态的原理是,在程序运行时确定调用的函数版本,而不是在编译时确定。因此,可以通过基类指针或引用来调用派生类的虚函数,从而实现运行时多态性。
虚函数必须以与其重载函数相同的参数列表和返回类型进行重载。同时,虚函数也可以被纯虚函数和抽象类所使用,这会涉及到更高级别的面向对象设计思想,如接口和实现分离等。

说说c++11新特性

  • 自动类型推导(auto):使用关键字“auto”可以让编译器自动推导变量类型,减少代码量并提高可读性。
  • 范围for循环:使得遍历数组、容器等数据结构更加方便。
  • 右值引用(Rvalue Reference):提供了对临时变量的引用,并允许在函数参数和返回值中使用临时对象。
  • 移动语义(Move Semantics):通过右值引用来实现对对象的快速移动而不是复制,提高程序效率。
  • 智能指针(Smart Pointers):提供了RAII机制,避免了手动管理内存的麻烦,同时防止了内存泄漏和野指针等问题。
  • lambda表达式:匿名函数,可以方便地定义简单的函数对象。
  • 静态断言(static_assert):编译时检查常量表达式是否满足条件。
  • 线程支持库(Thread Support Library):为多线程编程提供了标准库级别的支持。
  • 强类型枚举(Scoped Enumerations):在枚举类中定义枚举常量时,可以限制它们的作用域。
  • 随机数生成器(Random Number Generators):提供了多种随机数生成算法。

讲讲智能指针

智能指针是一种对象,行为类似于指针,但具有自动管理所指向对象生命周期的功能。

std::shared_ptr允许多个智能指针共享同一个对象,并且会自动计数引用该对象的智能指针数量。当引用计数降为0时,即没有任何智能指针使用该对象,该对象会被自动删除。std::shared_ptr还支持自定义删除器,可在实例化时传入一个函数来指定删除对象的方式。

std::unique_ptr则不允许多个智能指针共享同一个对象,只能有一个所有权,它可以通过std::move转移所有权,但不能直接复制或赋值。当std::unique_ptr超出作用域时,它指向的对象也会被自动删除。

讲讲右值引用

与左值引用类似,是用来引用变量的,区别在于右值引用可以引用临时对象或者表达式产生的结果。

右值引用还有一个很重要的用途就是支持移动语义。在C++11中,我们可以定义一个移动构造函数和一个移动赋值运算符,利用右值引用来实现对于数据的高效移动,而不是进行不必要的拷贝操作。

讲一下多线程

多线程是指在一个程序中同时执行多个独立的线程,每个线程都有自己的代码执行流程、栈和局部变量等资源。通过多线程技术可以充分利用多核处理器的计算能力以及提高程序的并发性和响应性。

在多线程编程中,通常存在一个主线程和多个子线程。主线程负责程序的初始化和管理,而子线程则负责完成任务。由于每个线程都可以独立执行,因此可以提高程序的效率和性能。

linux了解吗?

说说常用指令

  • ls:列出当前目录下的文件和子目录。
  • cd:改变当前目录。
  • pwd:显示当前目录的路径。
  • cp:拷贝文件或目录。
  • mv:移动文件或目录,也可用于重命名文件或目录。
  • rm:删除文件或目录。
  • mkdir:创建新目录。
  • rmdir:删除空目录。
  • touch:创建新文件或更新已有文件的时间戳。
  • cat:将文件内容输出到终端。
  • less:分页显示文件内容。
  • head:显示文件前几行。
  • tail:显示文件后几行。
  • grep:在文件中查找指定字符串或正则表达式。
  • find:在文件系统中查找符合条件的文件或目录。
  • top:实时显示系统资源使用情况。
  • ps:列出当前系统进程信息。
  • kill:终止指定进程。

网络出现故障一般用什么指令排查?

  • ping:用于测试网络是否连通。通过发送ICMP请求到目标主机并等待响应来判断网络是否正常。
  • traceroute:用于追踪数据包在互联网上的路径,以及判断数据包经过的路由节点的响应时间。
  • netstat:用于显示当前网络连接状态和统计信息。可以查看本地系统与其他主机之间的连接数、端口监听情况等信息。
  • ifconfig/ip addr:用于查看和配置网络接口信息,包括IP地址、子网掩码、网关等信息。
  • curl/wget:用于测试网络连接是否正常和下载文件。可以获取指定URL的内容或文件,并判断下载速度等。
  • nslookup/dig:用于进行DNS查询,以确定域名解析是否正常。
  • tcpdump:用于捕获和分析网络数据流量,以便诊断网络问题和安全问题。

讲一下TCP如何建立链接?

它使用三次握手来建立连接

  • 客户端向服务端发送一个带有SYN标志位的数据包,表示请求建立连接。此时客户端进入SYN_SENT状态。

  • 服务端收到请求后,回复一个带有SYN/ACK标志位的数据包,表示同意建立连接。同时,将自己的初始序列号(ISN)放在TCP首部中。此时服务端进入SYN_RCVD状态。

  • 客户端再次向服务端发送一个带有ACK标志位和确认号(ACK number)的数据包,表示接受服务端的请求,并确认自己的ISN。此时客户端进入ESTABLISHED状态,服务端也进入ESTABLISHED状态,连接建立成功。

手撕代码经典dfs统计岛屿数量

  • 遍历整个地图,从第一个非海洋方格开始进行搜索。
  • 对于每个搜索到的陆地方格,向它的上、下、左、右四个方向扩展搜索,找到所有与之相邻且未被访问过的陆地方格,并标记为已访问。
  • 继续遍历地图,直到所有的陆地方格都被访问过。
  • 记录搜索到的陆地方格的数量即可。