笔面试题记录

最近经历了几次笔面试,记性也不太好,简单记录一下有印象的题目。

1.高响应比调度(Highest Response Ratio Next,简称HRRN)

是一种用于进程调度的算法,旨在通过动态计算响应比来选择下一个要执行的进程。

等待时间是指进程在就绪队列中等待执行的时间,服务时间是指进程已经执行的时间或者需要执行的时间。

计算响应比的公式通常如下:

响应比 = (等待时间 + 服务时间) / 服务时间

在每个时间片结束时,调度器选择具有最高响应比的进程来执行。这意味着等待时间长且服务时间短的进程将具有更高的响应比,从而更有可能被选择执行。这种方式可以确保长时间等待的进程有机会获得执行,并且避免了短作业优先调度算法中可能出现的饥饿现象。

2.C++中引用可以再指向NULL吗?

在C++中,引用不能直接指向`NULL`(或者空指针)。

引用必须在初始化时绑定到一个有效的对象,且一旦绑定后,它将一直引用该对象,无法更改引用的目标。

当我们尝试将引用初始化为`NULL`时,会导致编译错误。例如:

```cpp
int* ptr = NULL;
int& ref = *ptr;  // 错误:引用无法绑定到NULL指针
```

上述代码尝试将引用`ref`绑定到一个指向`NULL`的指针`ptr`,但这是不允许的。

引用要求始终引用一个有效的对象,它是一个有效的别名。因此,在使用引用之前,必须确保它已被正确地初始化,并且引用的对象在其生命周期内保持有效。

3. SQL :> ALL

> ALL是比较运算符之一,用于比较一个值和一组值,并返回满足某个条件的结果。

```sql
SELECT column_name
FROM table_name
WHERE column_name > ALL (SELECT column_name FROM another_table)
```

在上面的示例中,`column_name` 是要比较的列名,`table_name` 是主查询中的表名。子查询 `(SELECT column_name FROM another_table)` 返回一个值集合,然后将主查询中的 `column_name` 与该集合中的每个值进行比较。只有当主查询的值大于所有集合中的值时,才会返回匹配的结果。

需要注意的是,使用 `> ALL` 进行比较时,必须确保右侧的值集合不为空,否则将导致结果不确定或出现错误。

4.循环队列

循环队列(Circular Queue),也称为环形缓冲区,是一种具有固定大小的队列数据结构,其中队尾和队头连接在一起,形成一个环。

传统的队列(线性队列)在队尾添加元素时,如果队列已满,则无法添加新元素。而循环队列通过循环利用队列中未使用的空间,实现了队尾添加元素时的循环存储。当队尾指针(rear)指向队列的最后一个位置时,如果队列的前面还有空闲位置,新的元素可以被添加到队列的开头。

循环队列的特点包括:

  • 使用数组或环形缓冲区作为底层存储结构,具有固定的大小。
  • 使用队头指针(front)和队尾指针(rear)来跟踪队列中的元素。
  • 当队列为空时,front 和 rear 指针相等。当队列满时,rear 指针的下一个位置是 front 指针。
  • 入队和出队操作都在常数时间复杂度(O(1))内完成。
  • 循环队列可以用于解决需要循环利用有限资源的问题,例如缓冲区管理、循环任务调度等。

5.C++中哪些操作符不可以重载

  •  成员访问操作符(`.`):用于访问类的成员,不能被重载。
  •  成员指针访问操作符(`.*` 和 `->*`):用于通过成员指针访问类的成员,同样不能被重载。
  •  作用域解析操作符(`::`):用于指定命名空间或类的作用域,也不能被重载。
  •  条件操作符(`?:`):用于条件表达式,不能进行重载。
  •  sizeof 操作符:用于获取对象或类型的大小,在 C++ 中不可重载。
  •  类型转换操作符(`static_cast`、`dynamic_cast`、`const_cast`、`reinterpret_cast`):这些类型转换操作符虽然看起来像是函数调用,但实际上它们是一种特殊的操作符,不允许进行重载。

需要注意的是,即使有些操作符不允许进行重载,但对于用户自定义的类型,可以通过重载其他操作符来实现相应的功能。重载操作符允许我们定义自定义类型的行为,使其更符合特定的需求和语义。

6. 成员指针访问操作符 `.*` 和 `->*`

成员指针:直接指向某个类的成员的指针,并不通过对象来指向。

int A::*p = &A::member;

double (A::*p)(double) = &A::func;

 `.*` 操作符:用于通过成员指针访问类的非静态成员。它的语法形式为 `对象.*成员指针`,表示通过对象和成员指针来访问相应的成员。

   ```cpp
   class MyClass {
   public:
       int member;
   };

   int main() {
       MyClass obj;
       int MyClass::*ptr = &MyClass::member;
       obj.*ptr = 42;  // 通过成员指针访问成员
       return 0;
   }
   ```

   上述示例中,通过 `obj.*ptr` 的方式,使用成员指针 `ptr` 来访问 `obj` 对象的成员 `member`。

`->*` 操作符:类似于 `.*` 操作符,但用于通过成员指针访问类的成员函数。它的语法形式为 `对象指针->*成员函数指针`。

   ```cpp
   class MyClass {
   public:
       void memberFunc(int value) {
           // ...
       }
   };

   int main() {
       MyClass obj;
       void (MyClass::*funcPtr)(int) = &MyClass::memberFunc;
       MyClass* ptr = &obj;
       (ptr->*funcPtr)(42);  // 通过成员函数指针调用成员函数
       return 0;
   }
   ```

   在上述示例中,通过 `(ptr->*funcPtr)(42)` 的方式,使用成员函数指针 `funcPtr` 来调用 `ptr` 指向的对象的成员函数 `memberFunc`。

7.python和java的垃圾回收机制有什么不同?

Python的垃圾回收机制:
Python使用了一种称为"引用计数"的垃圾回收机制。在Python中,每个对象都有一个引用计数器,用于跟踪对象被引用的次数。当对象的引用计数降为0时,即没有任何引用指向该对象时,Python的垃圾回收机制会自动回收该对象占用的内存。此外,Python还使用了其他策略,如循环垃圾收集(Cycle Detection),用于处理循环引用的情况。

Java的垃圾回收机制:
Java使用了基于"可达性分析"的垃圾回收机制。在Java中,垃圾回收器通过确定对象是否可由根对象(如活动线程、静态变量等)访问来确定对象的可达性。如果对象不可由根对象访问,则被判定为垃圾对象,并由垃圾回收器进行回收。Java中的垃圾回收器使用了不同的算法,如标记-清除(Mark and Sweep)、复制(Copying)、标记-整理(Mark and Compact)等。

主要的不同点包括:
1. 回收策略:Python使用引用计数和循环垃圾收集,而Java使用可达性分析和不同的垃圾回收算法。
2. 动态内存分配:Python的垃圾回收机制处理动态内存分配方面相对简单,通过引用计数来跟踪对象的生命周期。而Java的垃圾回收器需要管理更复杂的堆内存,包括分代回收等技术。
3. 垃圾回收器的实现:Python的垃圾回收机制是由解释器自身实现的,而Java的垃圾回收器是由Java虚拟机(JVM)提供的。

8.gdb时如何生成debug版本?

在Makefile中编译命令中gcc -o project project.c -std=c99 加入-g

常用的gcc命令选项:

  • -c:只编译源文件,生成目标文件(.o文件),不进行链接操作。
  • -o output file:指定输出文件的名称。
  • -Wall:启用警告信息。
  • -g:生成调试信息,用于调试程序。
  • -std=standard:指定使用的C或C++标准。
  • -I directory:添加头文件搜索路径。
  • -L directory:添加库文件搜索路径。
  • -l library:链接指定的库文件。
  • -D macro:定义宏。
  • -E:只进行预处理,生成预处理后的文件。
  • -S:只进行编译,生成汇编语言文件。

gdb(GNU Debugger)是一个用于调试程序的开源调试器。

它提供了一组命令,用于与正在运行的程序进行交互,以便于调试和分析代码。

下面是一些常用的`gdb`命令:

  • 启动和退出:

    • gdb program:启动gdb并加载指定的可执行文件。
    • run:运行程序。
    • quit:退出gdb
  • 断点设置和删除:

    • break function:在函数入口处设置断点。
    • break filename:line:在指定文件的指定行设置断点。
    • delete breakpoints:删除所有断点。
  • 执行程序:

    • run:运行程序。
    • continue:继续执行程序。
    • next:执行下一行代码。
    • step:单步执行,进入函数调用。
    • finish:执行到当前函数返回。
  • 查看和修改变量:

    • print variable:打印变量的值。
    • display variable:在每次停止时显示变量的值。
    • set variable = value:修改变量的值。
  • 回溯和堆栈:

    • backtrace:打印函数调用堆栈。
    • frame n:切换到指定帧。
    • info locals:显示当前帧的局部变量。
    • info args:显示当前帧的函数参数。
  • 内存和地址:

    • x /fmt address:以指定格式查看内存地址的内容。
    • info registers:显示寄存器的值。
  • 调试器控制:

    • break:列出所有断点。
    • disable breakpoint n:禁用指定断点。
    • enable breakpoint n:启用指定断点。
    • ignore breakpoint n count:忽略指定断点的前几次触发。
    • set pagination off:禁用分页。

9.Linux常用命令

Linux系统提供了许多命令行工具,用于管理和操作系统。下面是一些常用的Linux系统命令:

文件和目录操作:

   - `ls`:列出目录内容。
   - `cd`:切换工作目录。
   - `pwd`:显示当前工作目录的路径。
   - `mkdir`:创建新目录。
   - `rm`:删除文件或目录。
   - `cp`:复制文件或目录。
   - `mv`:移动或重命名文件或目录。

文件查看和编辑:

   - `cat`:将文件内容输出到终端。
   - `less`:分页查看文件内容。
   - `head`:显示文件的开头部分。
   - `tail`:显示文件的末尾部分。
   - `vi`或`vim`:文本编辑器,用于编辑文件。

文件权限和所有权管理:

   - `chmod`:修改文件或目录的权限。
   - `chown`:修改文件或目录的所有者。
   - `chgrp`:修改文件或目录的所属组。

系统信息和进程管理:

   - `uname`:显示系统信息。
   - `whoami`:显示当前登录用户名。
   - `ps`:显示运行中的进程。
   - `top`:实时显示系统资源占用情况和进程列表。
   - `kill`:终止指定进程。
   - `shutdown`:关闭系统。

网络管理:

   - `ifconfig`:显示和配置网络接口信息。
   - `ping`:向指定主机发送网络请求并接收回复。
   - `ssh`:远程登录到其他主机。
   - `scp`:在本地主机和远程主机之间复制文件。
   - `wget`:下载文件。

压缩和解压缩:

   - `tar`:打包和解包文件。
   - `gzip`:压缩文件。
   - `gunzip`:解压缩文件。

其他常用命令:

   - `echo`:将文本输出到终端或文件。
   - `grep`:在文件中搜索指定的模式。
   - `find`:在文件系统中查找文件。
   - `date`:显示或设置系统日期和时间。
   - `history`:显示最近执行过的命令历史记录。

你可能感兴趣的:(C++,开发语言,面试)