mirror of
https://github.com/huihut/interview.git
synced 2025-12-16 20:17:08 +03:00
update docsify
This commit is contained in:
321
docs/README.md
321
docs/README.md
@@ -220,37 +220,37 @@ using namespace std;
|
||||
class Base
|
||||
{
|
||||
public:
|
||||
inline virtual void who()
|
||||
{
|
||||
cout << "I am Base\n";
|
||||
}
|
||||
virtual ~Base() {}
|
||||
inline virtual void who()
|
||||
{
|
||||
cout << "I am Base\n";
|
||||
}
|
||||
virtual ~Base() {}
|
||||
};
|
||||
class Derived : public Base
|
||||
{
|
||||
public:
|
||||
inline void who() // 不写inline时隐式内联
|
||||
{
|
||||
cout << "I am Derived\n";
|
||||
}
|
||||
inline void who() // 不写inline时隐式内联
|
||||
{
|
||||
cout << "I am Derived\n";
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
// 此处的虚函数 who(),是通过类(Base)的具体对象(b)来调用的,编译期间就能确定了,所以它可以是内联的,但最终是否内联取决于编译器。
|
||||
Base b;
|
||||
b.who();
|
||||
// 此处的虚函数 who(),是通过类(Base)的具体对象(b)来调用的,编译期间就能确定了,所以它可以是内联的,但最终是否内联取决于编译器。
|
||||
Base b;
|
||||
b.who();
|
||||
|
||||
// 此处的虚函数是通过指针调用的,呈现多态性,需要在运行时期间才能确定,所以不能为内联。
|
||||
Base *ptr = new Derived();
|
||||
ptr->who();
|
||||
// 此处的虚函数是通过指针调用的,呈现多态性,需要在运行时期间才能确定,所以不能为内联。
|
||||
Base *ptr = new Derived();
|
||||
ptr->who();
|
||||
|
||||
// 因为Base有虚析构函数(virtual ~Base() {}),所以 delete 时,会先调用派生类(Derived)析构函数,再调用基类(Base)析构函数,防止内存泄漏。
|
||||
delete ptr;
|
||||
ptr = nullptr;
|
||||
// 因为Base有虚析构函数(virtual ~Base() {}),所以 delete 时,会先调用派生类(Derived)析构函数,再调用基类(Base)析构函数,防止内存泄漏。
|
||||
delete ptr;
|
||||
ptr = nullptr;
|
||||
|
||||
system("pause");
|
||||
return 0;
|
||||
system("pause");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -283,24 +283,43 @@ assert( p != NULL ); // assert 不可用
|
||||
* sizeof 对数组,得到整个数组所占空间大小。
|
||||
* sizeof 对指针,得到指针本身所占空间大小。
|
||||
|
||||
### #pragma pack(n)
|
||||
### 编译器扩展与标准对齐控制
|
||||
|
||||
设定结构体、联合以及类成员变量以 n 字节方式对齐
|
||||
* 编译器扩展:`#pragma pack(n)`,将随后定义的 `struct`/`class`/`union` 的成员最大对齐限制为 n 字节。
|
||||
* 标准对齐控制:
|
||||
* `alignas(k)`,要求类型或变量至少按 k 字节对齐(向上取整到 ≥ 自然对齐)。
|
||||
* `alignof(T)`,获取类型 T 的自然对齐要求(编译时常量)。
|
||||
|
||||
#pragma pack(n) 使用
|
||||
特性 |#pragma pack|alignas
|
||||
--------|--------------|------------
|
||||
标准化 |❌ 编译器扩展 | ✅ C++11标准
|
||||
对齐方向|⬇️ 只能减小对齐| ⬆️ 只能增大对齐
|
||||
可移植性|❌ 编译器依赖 | ✅ 跨平台
|
||||
作用范围|🔄 影响整个结构| 🎯 可针对单个成员
|
||||
性能影响|⚠️ 可能降低内存访问速度| ⚠️ 过度对齐浪费空间
|
||||
|
||||
使用
|
||||
|
||||
```cpp
|
||||
#pragma pack(push) // 保存对齐状态
|
||||
#pragma pack(4) // 设定为 4 字节对齐
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
|
||||
struct test
|
||||
{
|
||||
char m1;
|
||||
double m4;
|
||||
int m3;
|
||||
#pragma pack(push, 1) // 最大对齐 1 字节,紧凑布局
|
||||
struct PackedHeader {
|
||||
uint16_t len; // offset 0
|
||||
uint32_t id; // offset 2
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct alignas(8) Align8 {
|
||||
double value; // offset 0, 占 8 字节
|
||||
int flag; // offset 8
|
||||
};
|
||||
|
||||
#pragma pack(pop) // 恢复对齐状态
|
||||
int main() {
|
||||
std::cout << "PackedHeader size: " << sizeof(PackedHeader) << "\n"; // 6
|
||||
std::cout << "Align8 size: " << sizeof(Align8) << "\n"; // 16
|
||||
}
|
||||
```
|
||||
|
||||
### 位域
|
||||
@@ -315,14 +334,14 @@ Bit mode: 2; // mode 占 2 位
|
||||
* 位域的类型必须是整型或枚举类型,带符号类型中的位域的行为将因具体实现而定
|
||||
* 取地址运算符(&)不能作用于位域,任何指针都无法指向类的位域
|
||||
|
||||
### extern "C"
|
||||
### extern 与 extern "C"
|
||||
|
||||
* 被 extern 限定的函数或变量是 extern 类型的
|
||||
* 被 `extern "C"` 修饰的变量和函数是按照 C 语言方式编译和链接的
|
||||
* `extern` 是存储类说明符(storage-class-specifier),用于声明变量或函数具有外部链接,表示实体的定义可能在其他翻译单元中。
|
||||
* `extern "C"` 是链接指示(linkage directive),它指定函数或变量使用 C 语言链接(不影响编译规则)。
|
||||
1. 禁止 C++ 名称修饰。确保符号名称与该平台下 C 编译器生成的名称一致,避免链接时因名称修饰导致的未定义符号错误,但不保证平台 ABI(应用二进制接口)一致性。
|
||||
2. 实现 C/C++ 互操作。允许 C++ 函数被 C 代码调用(或反之)。
|
||||
|
||||
`extern "C"` 的作用是让 C++ 编译器将 `extern "C"` 声明的代码当作 C 语言代码处理,可以避免 C++ 因符号修饰导致代码不能和C语言库中的符号进行链接的问题。
|
||||
|
||||
extern "C" 使用
|
||||
`extern "C"` 使用
|
||||
|
||||
```cpp
|
||||
#ifdef __cplusplus
|
||||
@@ -476,14 +495,14 @@ explicit 使用
|
||||
```cpp
|
||||
struct A
|
||||
{
|
||||
A(int) { }
|
||||
operator bool() const { return true; }
|
||||
A(int) { }
|
||||
operator bool() const { return true; }
|
||||
};
|
||||
|
||||
struct B
|
||||
{
|
||||
explicit B(int) {}
|
||||
explicit operator bool() const { return true; }
|
||||
explicit B(int) {}
|
||||
explicit operator bool() const { return true; }
|
||||
};
|
||||
|
||||
void doA(A a) {}
|
||||
@@ -492,29 +511,29 @@ void doB(B b) {}
|
||||
|
||||
int main()
|
||||
{
|
||||
A a1(1); // OK:直接初始化
|
||||
A a2 = 1; // OK:复制初始化
|
||||
A a3{ 1 }; // OK:直接列表初始化
|
||||
A a4 = { 1 }; // OK:复制列表初始化
|
||||
A a5 = (A)1; // OK:允许 static_cast 的显式转换
|
||||
doA(1); // OK:允许从 int 到 A 的隐式转换
|
||||
if (a1); // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换
|
||||
bool a6(a1); // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换
|
||||
bool a7 = a1; // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换
|
||||
bool a8 = static_cast<bool>(a1); // OK :static_cast 进行直接初始化
|
||||
A a1(1); // OK:直接初始化
|
||||
A a2 = 1; // OK:复制初始化
|
||||
A a3{ 1 }; // OK:直接列表初始化
|
||||
A a4 = { 1 }; // OK:复制列表初始化
|
||||
A a5 = (A)1; // OK:允许 static_cast 的显式转换
|
||||
doA(1); // OK:允许从 int 到 A 的隐式转换
|
||||
if (a1); // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换
|
||||
bool a6(a1); // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换
|
||||
bool a7 = a1; // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换
|
||||
bool a8 = static_cast<bool>(a1); // OK :static_cast 进行直接初始化
|
||||
|
||||
B b1(1); // OK:直接初始化
|
||||
B b2 = 1; // 错误:被 explicit 修饰构造函数的对象不可以复制初始化
|
||||
B b3{ 1 }; // OK:直接列表初始化
|
||||
B b4 = { 1 }; // 错误:被 explicit 修饰构造函数的对象不可以复制列表初始化
|
||||
B b5 = (B)1; // OK:允许 static_cast 的显式转换
|
||||
doB(1); // 错误:被 explicit 修饰构造函数的对象不可以从 int 到 B 的隐式转换
|
||||
if (b1); // OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool 的按语境转换
|
||||
bool b6(b1); // OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool 的按语境转换
|
||||
bool b7 = b1; // 错误:被 explicit 修饰转换函数 B::operator bool() 的对象不可以隐式转换
|
||||
bool b8 = static_cast<bool>(b1); // OK:static_cast 进行直接初始化
|
||||
B b1(1); // OK:直接初始化
|
||||
B b2 = 1; // 错误:被 explicit 修饰构造函数的对象不可以复制初始化
|
||||
B b3{ 1 }; // OK:直接列表初始化
|
||||
B b4 = { 1 }; // 错误:被 explicit 修饰构造函数的对象不可以复制列表初始化
|
||||
B b5 = (B)1; // OK:允许 static_cast 的显式转换
|
||||
doB(1); // 错误:被 explicit 修饰构造函数的对象不可以从 int 到 B 的隐式转换
|
||||
if (b1); // OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool 的按语境转换
|
||||
bool b6(b1); // OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool 的按语境转换
|
||||
bool b7 = b1; // 错误:被 explicit 修饰转换函数 B::operator bool() 的对象不可以隐式转换
|
||||
bool b8 = static_cast<bool>(b1); // OK:static_cast 进行直接初始化
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -559,7 +578,7 @@ Derived(parms) : Base(args) { }
|
||||
`using 指示` 使得某个特定命名空间中所有名字都可见,这样我们就无需再为它们添加任何前缀限定符了。如:
|
||||
|
||||
```cpp
|
||||
using namespace_name name;
|
||||
using namespace namespace_name;
|
||||
```
|
||||
|
||||
#### 尽量少使用 `using 指示` 污染命名空间
|
||||
@@ -608,24 +627,24 @@ int count = 11; // 全局(::)的 count
|
||||
|
||||
class A {
|
||||
public:
|
||||
static int count; // 类 A 的 count(A::count)
|
||||
static int count; // 类 A 的 count(A::count)
|
||||
};
|
||||
int A::count = 21;
|
||||
|
||||
void fun()
|
||||
{
|
||||
int count = 31; // 初始化局部的 count 为 31
|
||||
count = 32; // 设置局部的 count 的值为 32
|
||||
int count = 31; // 初始化局部的 count 为 31
|
||||
count = 32; // 设置局部的 count 的值为 32
|
||||
}
|
||||
|
||||
int main() {
|
||||
::count = 12; // 测试 1:设置全局的 count 的值为 12
|
||||
::count = 12; // 测试 1:设置全局的 count 的值为 12
|
||||
|
||||
A::count = 22; // 测试 2:设置类 A 的 count 为 22
|
||||
A::count = 22; // 测试 2:设置类 A 的 count 为 22
|
||||
|
||||
fun(); // 测试 3
|
||||
fun(); // 测试 3
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -807,7 +826,7 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
#### 动态多态(运行期期/晚绑定)
|
||||
#### 动态多态(运行期/晚绑定)
|
||||
* 虚函数:用 virtual 修饰成员函数,使其成为虚函数
|
||||
* 动态绑定:当使用基类的引用或指针调用一个虚函数时将发生动态绑定
|
||||
|
||||
@@ -931,9 +950,9 @@ virtual int A() = 0;
|
||||
* 虚函数不占用存储空间
|
||||
* 虚函数表存储的是虚函数地址
|
||||
|
||||
### 模板类、成员模板、虚函数
|
||||
### 类模板、成员模板、虚函数
|
||||
|
||||
* 模板类中可以使用虚函数
|
||||
* 类模板中可以使用虚函数
|
||||
* 一个类(无论是普通类还是类模板)的成员模板(本身是模板的成员函数)不能是虚函数
|
||||
|
||||
### 抽象类、接口类、聚合类
|
||||
@@ -1019,22 +1038,6 @@ new (place_address) type [size] { braced initializer list }
|
||||
3. 必须保证成员函数的 `delete this ` 后面没有调用 this 了
|
||||
4. 必须保证 `delete this` 后没有人使用了
|
||||
|
||||
### 如何定义一个只能在堆上(栈上)生成对象的类?
|
||||
|
||||
> [如何定义一个只能在堆上(栈上)生成对象的类?](https://www.nowcoder.com/questionTerminal/0a584aa13f804f3ea72b442a065a7618)
|
||||
|
||||
#### 只能在堆上
|
||||
|
||||
方法:将析构函数设置为私有
|
||||
|
||||
原因:C++ 是静态绑定语言,编译器管理栈上对象的生命周期,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性。若析构函数不可访问,则不能在栈上创建对象。
|
||||
|
||||
#### 只能在栈上
|
||||
|
||||
方法:将 new 和 delete 重载为私有
|
||||
|
||||
原因:在堆上生成对象,使用 new 关键词操作,其过程分为两阶段:第一阶段,使用 new 在堆上寻找可用内存,分配给对象;第二阶段,调用构造函数生成对象。将 new 操作设置为私有,那么第一阶段就无法完成,就不能够在堆上生成对象。
|
||||
|
||||
### 智能指针
|
||||
|
||||
#### C++ 标准库(STL)中
|
||||
@@ -1071,7 +1074,7 @@ weak_ptr 允许你共享但不拥有某对象,一旦最末一个拥有该对
|
||||
|
||||
##### unique_ptr
|
||||
|
||||
unique_ptr 是 C++11 才开始提供的类型,是一种在异常时可以帮助避免资源泄漏的智能指针。采用独占式拥有,意味着可以确保一个对象和其相应的资源同一时间只被一个 pointer 拥有。一旦拥有着被销毁或编程 empty,或开始拥有另一个对象,先前拥有的那个对象就会被销毁,其任何相应资源亦会被释放。
|
||||
unique_ptr 是 C++11 才开始提供的类型,是一种在异常时可以帮助避免资源泄漏的智能指针。采用独占式拥有,意味着可以确保一个对象和其相应的资源同一时间只被一个 pointer 拥有。一旦拥有者被销毁或变成空或开始拥有另一个对象,先前拥有的那个对象就会被销毁,其任何相应资源亦会被释放。
|
||||
|
||||
* unique_ptr 用于取代 auto_ptr
|
||||
|
||||
@@ -1090,37 +1093,62 @@ unique_ptr 是 C++11 才开始提供的类型,是一种在异常时可以帮
|
||||
|
||||
#### static_cast
|
||||
|
||||
* 用于非多态类型的转换
|
||||
* 不执行运行时类型检查(转换安全性不如 dynamic_cast)
|
||||
* 通常用于转换数值数据类型(如 float -> int)
|
||||
* 可以在整个类层次结构中移动指针,子类转化为父类安全(向上转换),父类转化为子类不安全(因为子类可能有不在父类的字段或方法)
|
||||
* 编译时类型转换(无运行时检查)
|
||||
* 不依赖 RTTI
|
||||
|
||||
> 向上转换是一种隐式转换。
|
||||
| 转换类型 | 安全性 | 示例 |
|
||||
|--------------------------|--------------|--------------------------|
|
||||
| 数值类型转换 | ✅ 安全 | `float f=3.14; int i=static_cast<int>(f);` |
|
||||
| 类向上转换 | ✅ 安全 | `Derived* d; Base* b=static_cast<Base*>(d);` |
|
||||
| 类向下转换 | ⚠️ 不安全 | `Base* b=new Base; Derived* d=static_cast<Derived*>(b);` |
|
||||
| 类不变转换 | ✅ 安全 | `MyClass* p; MyClass* same=static_cast<MyClass*>(p);` |
|
||||
| 显式构造函数调用 | ✅ 安全 | `func(static_cast<std::string>("text"));` |
|
||||
| 任意→void* | ✅ 安全 | `int* p; void* vp=static_cast<void*>(p);` |
|
||||
| 枚举↔整型 | ✅ 安全 | `enum Color{RED}; int c=static_cast<int>(RED);` |
|
||||
|
||||
#### dynamic_cast
|
||||
|
||||
* 用于多态类型的转换
|
||||
* 执行行运行时类型检查
|
||||
* 只适用于指针或引用
|
||||
* 对不明确的指针的转换将失败(返回 nullptr),但不引发异常
|
||||
* 可以在整个类层次结构中移动指针,包括向上转换、向下转换
|
||||
* 运行时类型检查(依赖 RTTI)
|
||||
* 多态类型要求(基类需至少一个虚函数)
|
||||
* 安全失败机制(nullptr 或异常)
|
||||
|
||||
#### const_cast
|
||||
| 转换类型 | 安全性 | 运行时开销 | 多态要求 | 失败处理 | 示例 |
|
||||
|--------------|--------|------------|----------|------------------------|------|
|
||||
| 类向上转换 | ✅ 安全 | 无 | ❌ 不需要 | 不适用(总是成功) | `Derived* d; Base* b = dynamic_cast<Base*>(d);` |
|
||||
| 类向下转换 | ✅ 安全 | 有 | ✅ 需要 | 指针→`nullptr`<br>引用→`std::bad_cast` | `Base* b=new Base; Derived* d = dynamic_cast<Derived*>(b);` |
|
||||
| 类旁支转换 | ✅ 安全 | 有 | ✅ 需要 | 指针→`nullptr`<br>引用→`std::bad_cast` | `B2* b2 = dynamic_cast<B2*>(b1); // 菱形继承中 B1*→B2*` |
|
||||
| 类不变转换 | ✅ 安全 | 无 | ❌ 不需要 | 不适用(总是成功) | `Derived* d2 = dynamic_cast<Derived*>(d1);` |
|
||||
| 任意→void* | ✅ 安全 | 有 | ✅ 需要 | `nullptr` | `void* p = dynamic_cast<void*>(obj);` |
|
||||
|
||||
* 用于删除 const、volatile 和 __unaligned 特性(如将 const int 类型转换为 int 类型 )
|
||||
#### const_cast
|
||||
|
||||
* 编译时类型修饰符操作
|
||||
* 仅修改 `const`/`volatile` 属性
|
||||
* 不改变底层二进制表示
|
||||
|
||||
| 转换类型 | 安全性 | 示例 |
|
||||
|------------------------|--------------|-------------------------------|
|
||||
| 移除 const | ⚠️ 风险 | `const int* cp; int* p=const_cast<int*>(cp);` |
|
||||
| 移除 volatile | ⚠️ 风险 | `volatile int* vp; int* p=const_cast<int*>(vp);` |
|
||||
| 添加 const | ✅ 安全 | `int* p; const int* cp=const_cast<const int*>(p);` |
|
||||
| 兼容旧式 API | ⚠️ 必要风险 | `legacy_api(const_cast<char*>(str.c_str()));` |
|
||||
|
||||
#### reinterpret_cast
|
||||
|
||||
* 用于位的简单重新解释
|
||||
* 滥用 reinterpret_cast 运算符可能很容易带来风险。 除非所需转换本身是低级别的,否则应使用其他强制转换运算符之一。
|
||||
* 允许将任何指针转换为任何其他指针类型(如 `char*` 到 `int*` 或 `One_class*` 到 `Unrelated_class*` 之类的转换,但其本身并不安全)
|
||||
* 也允许将任何整数类型转换为任何指针类型以及反向转换。
|
||||
* reinterpret_cast 运算符不能丢掉 const、volatile 或 __unaligned 特性。
|
||||
* reinterpret_cast 的一个实际用途是在哈希函数中,即,通过让两个不同的值几乎不以相同的索引结尾的方式将值映射到索引。
|
||||
* 无编译时类型安全检查
|
||||
* 二进制位级重新解释
|
||||
* 最危险的转换操作符
|
||||
|
||||
| 转换类型 | 安全性 | 示例 |
|
||||
|------------------------|--------------|-------------------------------|
|
||||
| 指针↔指针 | ❌ 高危 | `MyClass* obj; void* p=reinterpret_cast<void*>(obj);` |
|
||||
| 指针↔整型 | ❌ 高危 | `intptr_t addr=reinterpret_cast<intptr_t>(&obj);` |
|
||||
| 函数指针转换 | ❌ 极高危 | 不同签名函数指针转换 |
|
||||
| 内存映射 I/O | ⚠️ 系统编程 | 硬件寄存器访问 |
|
||||
|
||||
#### bad_cast
|
||||
|
||||
* 由于强制转换为引用类型失败,dynamic_cast 运算符引发 bad_cast 异常。
|
||||
* `dynamic_cast` 引用转换失败的异常类型。
|
||||
|
||||
bad_cast 使用
|
||||
|
||||
@@ -1135,14 +1163,10 @@ catch (bad_cast b) {
|
||||
|
||||
### 运行时类型信息 (RTTI)
|
||||
|
||||
#### dynamic_cast
|
||||
|
||||
* 用于多态类型的转换
|
||||
|
||||
#### typeid
|
||||
|
||||
* typeid 运算符允许在运行时确定对象的类型
|
||||
* type\_id 返回一个 type\_info 对象的引用
|
||||
* typeid 返回一个 type\_info 对象的引用
|
||||
* 如果想通过基类的指针获得派生类的数据类型,基类必须带有虚函数
|
||||
* 只能获取对象的实际类型
|
||||
|
||||
@@ -1207,11 +1231,11 @@ void doSomething(Flyable *obj) // 做些事情
|
||||
}
|
||||
|
||||
int main(){
|
||||
Bird *b = new Bird();
|
||||
doSomething(b);
|
||||
delete b;
|
||||
b = nullptr;
|
||||
return 0;
|
||||
Bird *b = new Bird();
|
||||
doSomething(b);
|
||||
delete b;
|
||||
b = nullptr;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1359,10 +1383,10 @@ int main(){
|
||||
|
||||
```cpp
|
||||
typedef struct {
|
||||
ElemType *elem;
|
||||
int top;
|
||||
int size;
|
||||
int increment;
|
||||
ElemType *elem;
|
||||
int top;
|
||||
int size;
|
||||
int increment;
|
||||
} SqStack;
|
||||
```
|
||||
|
||||
@@ -1374,10 +1398,10 @@ typedef struct {
|
||||
|
||||
```cpp
|
||||
typedef struct {
|
||||
ElemType * elem;
|
||||
int front;
|
||||
int rear;
|
||||
int maxSize;
|
||||
ElemType * elem;
|
||||
int front;
|
||||
int rear;
|
||||
int maxSize;
|
||||
}SqQueue;
|
||||
```
|
||||
|
||||
@@ -1405,10 +1429,10 @@ typedef struct {
|
||||
|
||||
```cpp
|
||||
typedef struct {
|
||||
ElemType *elem;
|
||||
int length;
|
||||
int size;
|
||||
int increment;
|
||||
ElemType *elem;
|
||||
int length;
|
||||
int size;
|
||||
int increment;
|
||||
} SqList;
|
||||
```
|
||||
|
||||
@@ -1488,14 +1512,14 @@ typedef struct LNode {
|
||||
typedef char KeyType;
|
||||
|
||||
typedef struct {
|
||||
KeyType key;
|
||||
KeyType key;
|
||||
}RcdType;
|
||||
|
||||
typedef struct {
|
||||
RcdType *rcd;
|
||||
int size;
|
||||
int count;
|
||||
bool *tag;
|
||||
RcdType *rcd;
|
||||
int size;
|
||||
int count;
|
||||
bool *tag;
|
||||
}HashTable;
|
||||
```
|
||||
|
||||
@@ -1839,12 +1863,12 @@ B树/B+树 |O(log<sub>2</sub>n) | |
|
||||
#### 进程之间的通信方式以及优缺点
|
||||
|
||||
* 管道(PIPE)
|
||||
* 有名管道:一种半双工的通信方式,它允许无亲缘关系进程间的通信
|
||||
* 有名管道(命名管道):一种先进先出的通信方式,它允许无亲缘关系进程间的通信
|
||||
* 优点:可以实现任意关系的进程间的通信
|
||||
* 缺点:
|
||||
1. 长期存于系统中,使用不当容易出错
|
||||
2. 缓冲区有限
|
||||
* 无名管道:一种半双工的通信方式,只能在具有亲缘关系的进程间使用(父子进程)
|
||||
* 无名管道(匿名管道):一种单工先进先出的通信方式,只能在具有亲缘关系的进程间使用(父子进程)
|
||||
* 优点:简单方便
|
||||
* 缺点:
|
||||
1. 局限于单向通信
|
||||
@@ -2013,14 +2037,14 @@ using namespace std;
|
||||
|
||||
int main()
|
||||
{
|
||||
int i = 0x12345678;
|
||||
int i = 0x12345678;
|
||||
|
||||
if (*((char*)&i) == 0x12)
|
||||
cout << "大端" << endl;
|
||||
else
|
||||
cout << "小端" << endl;
|
||||
if (*((char*)&i) == 0x12)
|
||||
cout << "大端" << endl;
|
||||
else
|
||||
cout << "小端" << endl;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -2159,7 +2183,7 @@ ICMP 报文格式:
|
||||
#### 内部网关协议
|
||||
|
||||
* RIP(Routing Information Protocol,路由信息协议)
|
||||
* OSPF(Open Sortest Path First,开放最短路径优先)
|
||||
* OSPF(Open Shortest Path First,开放最短路径优先)
|
||||
|
||||
#### 外部网关协议
|
||||
|
||||
@@ -2206,7 +2230,7 @@ ICMP 报文格式:
|
||||
|
||||
特征:
|
||||
* 面向连接
|
||||
* 只能点对点(一对一)通信
|
||||
* 端到端通信
|
||||
* 可靠交互
|
||||
* 全双工通信
|
||||
* 面向字节流
|
||||
@@ -2458,7 +2482,7 @@ TRACE | 回显服务器收到的请求,主要用于测试或诊断
|
||||
|
||||
##### 其他协议
|
||||
|
||||
* SMTP(Simple Main Transfer Protocol,简单邮件传输协议)是在 Internet 传输 Email 的标准,是一个相对简单的基于文本的协议。在其之上指定了一条消息的一个或多个接收者(在大多数情况下被确认是存在的),然后消息文本会被传输。可以很简单地通过 Telnet 程序来测试一个 SMTP 服务器。SMTP 使用 TCP 端口 25。
|
||||
* SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)是在 Internet 传输 Email 的标准,是一个相对简单的基于文本的协议。在其之上指定了一条消息的一个或多个接收者(在大多数情况下被确认是存在的),然后消息文本会被传输。可以很简单地通过 Telnet 程序来测试一个 SMTP 服务器。SMTP 使用 TCP 端口 25。
|
||||
* DHCP(Dynamic Host Configuration Protocol,动态主机设置协议)是一个局域网的网络协议,使用 UDP 协议工作,主要有两个用途:
|
||||
* 用于内部网络或网络服务供应商自动分配 IP 地址给用户
|
||||
* 用于内部网络管理员作为对所有电脑作中央管理的手段
|
||||
@@ -3431,5 +3455,4 @@ int main( void )
|
||||
|
||||
本仓库遵循 CC BY-NC-SA 4.0(署名 - 非商业性使用 - 相同方式共享) 协议,转载请注明出处,不得用于商业目的。
|
||||
|
||||
[](https://github.com/huihut/interview/blob/master/LICENSE)
|
||||
|
||||
[](https://github.com/huihut/interview/blob/master/LICENSE)
|
||||
326
docs/en.md
326
docs/en.md
@@ -225,37 +225,37 @@ using namespace std;
|
||||
class Base
|
||||
{
|
||||
public:
|
||||
inline virtual void who()
|
||||
{
|
||||
cout << "I am Base\n";
|
||||
}
|
||||
virtual ~Base() {}
|
||||
inline virtual void who()
|
||||
{
|
||||
cout << "I am Base\n";
|
||||
}
|
||||
virtual ~Base() {}
|
||||
};
|
||||
class Derived : public Base
|
||||
{
|
||||
public:
|
||||
inline void who() // Implicit inlining when not writing inline
|
||||
{
|
||||
cout << "I am Derived\n";
|
||||
}
|
||||
inline void who() // Implicit inlining when not writing inline
|
||||
{
|
||||
cout << "I am Derived\n";
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
// The virtual function who () here is called through the concrete object (b) of the class (Base), which can be determined during compilation, so it can be inlined, but whether it is inlined depends on the compilation Device.
|
||||
Base b;
|
||||
b.who();
|
||||
// The virtual function who () here is called through the concrete object (b) of the class (Base), which can be determined during compilation, so it can be inlined, but whether it is inlined depends on the compilation Device.
|
||||
Base b;
|
||||
b.who();
|
||||
|
||||
// The virtual function here is called through a pointer, which is polymorphic and needs to be determined during runtime, so it cannot be inlined.
|
||||
Base *ptr = new Derived();
|
||||
ptr->who();
|
||||
// The virtual function here is called through a pointer, which is polymorphic and needs to be determined during runtime, so it cannot be inlined.
|
||||
Base *ptr = new Derived();
|
||||
ptr->who();
|
||||
|
||||
// Because Base has a virtual destructor (virtual ~ Base () {}), when deleting, the Derived destructor is called first, and then the Base destructor is called to prevent memory leaks.
|
||||
delete ptr;
|
||||
ptr = nullptr;
|
||||
// Because Base has a virtual destructor (virtual ~ Base () {}), when deleting, the Derived destructor is called first, and then the Base destructor is called to prevent memory leaks.
|
||||
delete ptr;
|
||||
ptr = nullptr;
|
||||
|
||||
system("pause");
|
||||
return 0;
|
||||
system("pause");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -288,25 +288,46 @@ assert( p != NULL ); // assert is not available
|
||||
* sizeof For arrays - get the size of the entire array.
|
||||
* sizeof For pointers - get the size of the space occupied by the pointer itself.
|
||||
|
||||
### #pragma pack(n)
|
||||
### Compiler Extensions vs Standard Alignment Control
|
||||
|
||||
Set structure, union, and class member variables to be n-byte aligned
|
||||
* Compiler Extension `#pragma pack(n)`, restricts the maximum alignment of members in subsequently defined `struct`/`class`/`union` to n bytes.
|
||||
* Standard Alignment Control:
|
||||
* `alignas(k)`, requires types or variables to be aligned to at least k bytes (rounds up to ≥ natural alignment).
|
||||
* `alignof(T)`, gets the natural alignment requirement of type T (compile-time constant).
|
||||
|
||||
#pragma pack (n) use
|
||||
Feature | `#pragma pack` | `alignas`
|
||||
----------------|-------------------------|---------------------
|
||||
Standardization | ❌ Compiler Extension | ✅ C++11 Standard
|
||||
Alignment Direction | ⬇️ Only decreases alignment | ⬆️ Only increases alignment
|
||||
Portability | ❌ Compiler Dependent | ✅ Cross-platform
|
||||
Scope | 🔄 Affects entire struct | 🎯 Per-member control
|
||||
Performance Impact | ⚠️ May reduce memory access speed | ⚠️ Over-alignment wastes space
|
||||
|
||||
#### Usage Examples
|
||||
|
||||
```cpp
|
||||
#pragma pack(push) // save alignment state
|
||||
#pragma pack(4) // Set to 4 byte alignment
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
|
||||
struct test
|
||||
{
|
||||
char m1;
|
||||
double m4;
|
||||
int m3;
|
||||
#pragma pack(push, 1) // Max alignment 1 byte (compact layout)
|
||||
struct PackedHeader {
|
||||
uint16_t len; // offset 0
|
||||
uint32_t id; // offset 2
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct alignas(8) Align8 { // Force 8-byte alignment
|
||||
double value; // offset 0 (8 bytes)
|
||||
int flag; // offset 8
|
||||
};
|
||||
|
||||
#pragma pack(pop) // Restore alignment
|
||||
```
|
||||
int main() {
|
||||
std::cout << "PackedHeader size: "
|
||||
<< sizeof(PackedHeader) << "\n"; // Output: 6
|
||||
|
||||
std::cout << "Align8 size: "
|
||||
<< sizeof(Align8) << "\n"; // Output: 16
|
||||
}
|
||||
|
||||
### Bit field
|
||||
|
||||
@@ -320,14 +341,14 @@ A class can define its (non-static) data members as bit-fields, which contain a
|
||||
* The type of the bit field must be an integer or enumerated type. The behavior of the bit field in a signed type will depend on the implementation.
|
||||
* The fetch operator (&) cannot be applied to the bit field, and no pointer can point to the bit field of the class
|
||||
|
||||
### extern "C"
|
||||
### `extern` vs `extern "C"`
|
||||
|
||||
* Extern-qualified functions or variables are of type extern
|
||||
* Variables and functions decorated with `extern" C "` are compiled and linked in C
|
||||
* `extern` is a **storage-class specifier** used to declare that a variable or function has **external linkage**, indicating that the entity's definition may reside in another translation unit.
|
||||
* `extern "C"` is a **linkage directive** that specifies functions or variables should use **C language linkage** (without affecting compilation rules).
|
||||
1. **Suppresses C++ name mangling**: Ensures symbol names match those generated by the C compiler _on that specific platform_, preventing undefined symbol errors during linking due to name decoration. **Does not guarantee platform ABI (Application Binary Interface) consistency**.
|
||||
2. **Enables C/C++ interoperability**: Allows C++ functions to be called from C code (and vice versa).
|
||||
|
||||
The function of `extern" C "` is to let the C ++ compiler treat the code declared by `extern" C "` as C language code, which can avoid the problem that the code cannot be linked with the symbols in the C language library due to symbol modification. .
|
||||
|
||||
extern "C" demo
|
||||
`extern "C"` demo
|
||||
|
||||
```cpp
|
||||
#ifdef __cplusplus
|
||||
@@ -480,14 +501,14 @@ explicit demo
|
||||
```cpp
|
||||
struct A
|
||||
{
|
||||
A(int) { }
|
||||
operator bool() const { return true; }
|
||||
A(int) { }
|
||||
operator bool() const { return true; }
|
||||
};
|
||||
|
||||
struct B
|
||||
{
|
||||
explicit B(int) {}
|
||||
explicit operator bool() const { return true; }
|
||||
explicit B(int) {}
|
||||
explicit operator bool() const { return true; }
|
||||
};
|
||||
|
||||
void doA(A a) {}
|
||||
@@ -496,29 +517,29 @@ void doB(B b) {}
|
||||
|
||||
int main()
|
||||
{
|
||||
A a1(1); // OK:direct initialization
|
||||
A a2 = 1; // OK:copy initialization
|
||||
A a3{ 1 }; // OK:direct list initialization
|
||||
A a4 = { 1 }; // OK:copy list initialization
|
||||
A a5 = (A)1; // OK:Allow explicit conversion of static_cast
|
||||
doA(1); // OK:Allow implicit conversion from int to A
|
||||
if (a1); // OK: implicit conversion from A to bool using conversion function A ::operator bool()
|
||||
bool a6(a1); // OK: implicit conversion from A to bool using conversion function A::operator bool()
|
||||
bool a7 = a1; // OK: implicit conversion from A to bool using conversion function A::operator bool()
|
||||
bool a8 = static_cast<bool>(a1); // OK: static_cast for direct initialization
|
||||
A a1(1); // OK:direct initialization
|
||||
A a2 = 1; // OK:copy initialization
|
||||
A a3{ 1 }; // OK:direct list initialization
|
||||
A a4 = { 1 }; // OK:copy list initialization
|
||||
A a5 = (A)1; // OK:Allow explicit conversion of static_cast
|
||||
doA(1); // OK:Allow implicit conversion from int to A
|
||||
if (a1); // OK: implicit conversion from A to bool using conversion function A ::operator bool()
|
||||
bool a6(a1); // OK: implicit conversion from A to bool using conversion function A::operator bool()
|
||||
bool a7 = a1; // OK: implicit conversion from A to bool using conversion function A::operator bool()
|
||||
bool a8 = static_cast<bool>(a1); // OK: static_cast for direct initialization
|
||||
|
||||
B b1(1); // OK:direct initialization
|
||||
B b2 = 1; // Error: Object modified by explicit constructor cannot be initialized by copying
|
||||
B b3{ 1 }; // OK:direct list initialization
|
||||
B b4 = { 1 }; // Error: Object modified by explicit constructor cannot copy list initialization
|
||||
B b5 = (B)1; // OK: Allow explicit conversion of static_cast
|
||||
doB(1); // Error: Objects whose constructor is explicitly modified cannot be implicitly converted from int to B
|
||||
if (b1); // OK: objects modified by explicit conversion function B::operator bool() can be converted from B to bool by context
|
||||
bool b6(b1); // OK: Explicitly modified conversion function B::operator The object of bool() can be converted from B to bool by context
|
||||
bool b7 = b1; // Error: Objects modified by explicit conversion function B :: operator bool () cannot be implicitly converted
|
||||
bool b8 = static_cast<bool>(b1); // OK: static_cast performs direct initialization
|
||||
B b1(1); // OK:direct initialization
|
||||
B b2 = 1; // Error: Object modified by explicit constructor cannot be initialized by copying
|
||||
B b3{ 1 }; // OK:direct list initialization
|
||||
B b4 = { 1 }; // Error: Object modified by explicit constructor cannot copy list initialization
|
||||
B b5 = (B)1; // OK: Allow explicit conversion of static_cast
|
||||
doB(1); // Error: Objects whose constructor is explicitly modified cannot be implicitly converted from int to B
|
||||
if (b1); // OK: objects modified by explicit conversion function B::operator bool() can be converted from B to bool by context
|
||||
bool b6(b1); // OK: Explicitly modified conversion function B::operator The object of bool() can be converted from B to bool by context
|
||||
bool b7 = b1; // Error: Objects modified by explicit conversion function B :: operator bool () cannot be implicitly converted
|
||||
bool b8 = static_cast<bool>(b1); // OK: static_cast performs direct initialization
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -537,7 +558,7 @@ int main()
|
||||
A `using declaration` introduces only one member of a namespace at a time. It allows us to know exactly which name is referenced in the program. Such as:
|
||||
|
||||
```cpp
|
||||
using namespace_name :: name;
|
||||
using namespace_name::name;
|
||||
```
|
||||
|
||||
#### Using declaration of constructor
|
||||
@@ -563,7 +584,7 @@ Derived (parms): Base (args) {}
|
||||
The `using directive` makes all names in a particular namespace visible, so we don't need to add any prefix qualifiers to them. Such as:
|
||||
|
||||
```cpp
|
||||
using namespace_name name;
|
||||
using namespace namespace_name;
|
||||
```
|
||||
|
||||
#### Minimize `using directives` to pollute namespaces
|
||||
@@ -612,24 +633,24 @@ int count = 11; // Global (: :) count
|
||||
|
||||
class A {
|
||||
public:
|
||||
static int count; // Count (A::count) of class A
|
||||
static int count; // Count (A::count) of class A
|
||||
};
|
||||
int A::count = 21;
|
||||
|
||||
void fun()
|
||||
{
|
||||
int count = 31; // Initialize the local count to 31
|
||||
count = 32; // Set the local count to 32
|
||||
int count = 31; // Initialize the local count to 31
|
||||
count = 32; // Set the local count to 32
|
||||
}
|
||||
|
||||
int main() {
|
||||
::count = 12; // Test 1: Set the global count to 12
|
||||
::count = 12; // Test 1: Set the global count to 12
|
||||
|
||||
A::count = 22; // Test 2: Set the count of class A to 22
|
||||
A::count = 22; // Test 2: Set the count of class A to 22
|
||||
|
||||
fun(); // Test 3
|
||||
fun(); // Test 3
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -814,9 +835,11 @@ public:
|
||||
#### Dynamic polymorphism (runtime / late binding)
|
||||
|
||||
* Virtual functions: decorate member functions with virtual to make them virtual
|
||||
* Dynamic binding: dynamic binding occurs when a virtual function is called using a reference or pointer to a base class
|
||||
|
||||
**note:**
|
||||
|
||||
* You can assign an object of a derived class to a pointer or reference of the base class, and not vice versa
|
||||
* Ordinary functions (non-class member functions) cannot be virtual functions
|
||||
* Static functions (static) cannot be virtual functions
|
||||
* The constructor cannot be a virtual function (because when the constructor is called, the virtual table pointer is not in the object's memory space, the virtual table pointer must be formed after the constructor is called)
|
||||
@@ -1022,22 +1045,6 @@ Legal, but:
|
||||
3. You must ensure that the member function does not call this after `delete this`
|
||||
4. Make sure no one uses it after delete this
|
||||
|
||||
### How to define a class that can only generate objects on the heap (on the stack)?
|
||||
|
||||
> [How to define a class that can only generate objects on the heap (on the stack)?](https://www.nowcoder.com/questionTerminal/0a584aa13f804f3ea72b442a065a7618)
|
||||
|
||||
#### Only on the heap
|
||||
|
||||
Method: Make the destructor private
|
||||
|
||||
Reason: C ++ is a static binding language. The compiler manages the life cycle of objects on the stack. When the compiler allocates stack space for class objects, it first checks the accessibility of the class's destructor. If the destructor is not accessible, the object cannot be created on the stack.
|
||||
|
||||
#### Only on the stack
|
||||
|
||||
Method: overload new and delete as private
|
||||
|
||||
Reason: The object is generated on the heap using the new keyword operation. The process is divided into two stages: the first stage uses new to find available memory on the heap and allocates it to the object; the second stage calls the constructor to generate the object. By setting the new operation to private, the first phase cannot be completed, and objects cannot be generated on the heap.
|
||||
|
||||
### Smart pointer
|
||||
|
||||
#### In the C ++ Standard Library (STL)
|
||||
@@ -1093,37 +1100,62 @@ Deprecated by c ++ 11 due to lack of language features such as `std::move` seman
|
||||
|
||||
#### static_cast
|
||||
|
||||
* For non-polymorphic conversions
|
||||
* Do not perform runtime type checking (conversion security is not as good as dynamic_cast)
|
||||
* Usually used to convert numeric data types (such as float-> int)
|
||||
* You can move the pointer throughout the class hierarchy. It is safe (upward conversion) for a child class to be converted to a parent class, and it is not safe to convert a parent class to a child class (because a child class may have fields or methods that are not in the parent class)
|
||||
* Compile-time type conversion (no runtime checks)
|
||||
* Does not depend on RTTI
|
||||
|
||||
> Upcast is an implicit conversion.
|
||||
| Conversion Type | Safety | Example |
|
||||
|--------------------------|--------------|--------------------------|
|
||||
| Numeric conversion | ✅ Safe | `float f=3.14; int i=static_cast<int>(f);` |
|
||||
| Upcast (class hierarchy) | ✅ Safe | `Derived* d; Base* b=static_cast<Base*>(d);` |
|
||||
| Downcast (class hierarchy)| ⚠️ Unsafe | `Base* b=new Base; Derived* d=static_cast<Derived*>(b);` |
|
||||
| Same-type conversion | ✅ Safe | `MyClass* p; MyClass* same=static_cast<MyClass*>(p);` |
|
||||
| Explicit constructor call| ✅ Safe | `func(static_cast<std::string>("text"));` |
|
||||
| Any type→void* | ✅ Safe | `int* p; void* vp=static_cast<void*>(p);` |
|
||||
| Enum↔Integer | ✅ Safe | `enum Color{RED}; int c=static_cast<int>(RED);` |
|
||||
|
||||
#### dynamic_cast
|
||||
|
||||
* For polymorphic type conversions
|
||||
* Perform line runtime type checking
|
||||
* Only applicable to pointers or references
|
||||
* Conversion of ambiguous pointers will fail (return nullptr), but no exception will be thrown
|
||||
* You can move the pointer throughout the class hierarchy, including up conversion, down conversion
|
||||
* Runtime type checking (depends on RTTI)
|
||||
* Requires polymorphic type (base must have at least one virtual function)
|
||||
* Safe failure mechanism (nullptr or exception)
|
||||
|
||||
| Conversion Type | Safety | Runtime Cost | Polymorphic Required | Failure Handling | Example |
|
||||
|---------------------|--------|--------------|----------------------|---------------------------|---------|
|
||||
| Upcast | ✅ Safe | None | ❌ Not required | Not applicable (always succeeds) | `Derived* d; Base* b = dynamic_cast<Base*>(d);` |
|
||||
| Downcast | ✅ Safe | Yes | ✅ Required | Pointer→`nullptr`<br>Reference→`std::bad_cast` | `Base* b; Derived* d = dynamic_cast<Derived*>(b);` |
|
||||
| Cross-cast | ✅ Safe | Yes | ✅ Required | Pointer→`nullptr`<br>Reference→`std::bad_cast` | `B2* b2 = dynamic_cast<B2*>(b1); // In diamond inheritance` |
|
||||
| Same-type conversion| ✅ Safe | None | ❌ Not required | Not applicable (always succeeds) | `Derived* d2 = dynamic_cast<Derived*>(d1);` |
|
||||
| Any type→void* | ✅ Safe | Yes | ✅ Required | `nullptr` | `void* p = dynamic_cast<void*>(obj);` |
|
||||
|
||||
#### const_cast
|
||||
|
||||
* Used to remove const, volatile, and __unaligned features (such as converting const int to int)
|
||||
* Compile-time type modifier operation
|
||||
* Only modifies `const`/`volatile` attributes
|
||||
* Does not change underlying binary representation
|
||||
|
||||
| Conversion Type | Safety | Example |
|
||||
|------------------------|--------------|----------------------------------|
|
||||
| Remove const | ⚠️ Risky | `const int* cp; int* p=const_cast<int*>(cp);` |
|
||||
| Remove volatile | ⚠️ Risky | `volatile int* vp; int* p=const_cast<int*>(vp);` |
|
||||
| Add const | ✅ Safe | `int* p; const int* cp=const_cast<const int*>(p);` |
|
||||
| Legacy API compatibility | ⚠️ Necessary risk | `legacy_api(const_cast<char*>(str.c_str()));` |
|
||||
|
||||
#### reinterpret_cast
|
||||
|
||||
* Simple reinterpretation for bits
|
||||
* Misuse of the reinterpret_cast operator can be very risky. Unless the required conversion itself is low-level, you should use one of the other cast operators.
|
||||
* Allows conversion of any pointer to any other pointer type (such as `char *` to `int *` or `One_class *` to `Unrelated_class *`, but it is not itself safe)
|
||||
* Also allows conversion of any integer type to any pointer type and reverse conversion.
|
||||
* The reinterpret_cast operator cannot lose const, volatile, or __unaligned attributes.
|
||||
* A practical use of reinterpret_cast is in a hash function, which is to map values to indexes by making two different values hardly end with the same index.
|
||||
* No compile-time type safety checks
|
||||
* Binary bit-level reinterpretation
|
||||
* Most dangerous cast operator
|
||||
|
||||
| Conversion Type | Safety | Example |
|
||||
|------------------------|--------------|----------------------------------|
|
||||
| Pointer↔Pointer | ❌ High risk | `MyClass* obj; void* p=reinterpret_cast<void*>(obj);` |
|
||||
| Pointer↔Integer | ❌ High risk | `intptr_t addr=reinterpret_cast<intptr_t>(&obj);` |
|
||||
| Function pointer conversion | ❌ Extreme risk | Converting function pointers with different signatures |
|
||||
| Memory-mapped I/O | ⚠️ Systems programming | Hardware register access |
|
||||
|
||||
#### bad_cast
|
||||
|
||||
* The dynamic_cast operator throws a bad_cast exception because the cast to a reference type fails.
|
||||
* The exception type for a failed reference conversion using `dynamic_cast`.
|
||||
|
||||
bad_cast demo
|
||||
|
||||
@@ -1138,14 +1170,10 @@ catch (bad_cast b) {
|
||||
|
||||
### Runtime Type Information (RTTI)
|
||||
|
||||
#### dynamic_cast
|
||||
|
||||
* For polymorphic type conversions
|
||||
|
||||
#### typeid
|
||||
|
||||
* The typeid operator allows determining the type of an object at runtime
|
||||
* type \ _id returns a reference to a type \ _info object
|
||||
* typeid returns a reference to a type\_info object
|
||||
* If you want to get the data type of the derived class through the pointer of the base class, the base class must have a virtual function
|
||||
* Can only get the actual type of the object
|
||||
|
||||
@@ -1210,11 +1238,11 @@ void doSomething(Flyable *obj) // do something
|
||||
}
|
||||
|
||||
int main(){
|
||||
Bird *b = new Bird();
|
||||
doSomething(b);
|
||||
delete b;
|
||||
b = nullptr;
|
||||
return 0;
|
||||
Bird *b = new Bird();
|
||||
doSomething(b);
|
||||
delete b;
|
||||
b = nullptr;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1355,10 +1383,10 @@ Sequential stack data structures and pictures
|
||||
|
||||
```cpp
|
||||
typedef struct {
|
||||
ElemType *elem;
|
||||
int top;
|
||||
int size;
|
||||
int increment;
|
||||
ElemType *elem;
|
||||
int top;
|
||||
int size;
|
||||
int increment;
|
||||
} SqStack;
|
||||
```
|
||||
|
||||
@@ -1370,10 +1398,10 @@ Queue data structure
|
||||
|
||||
```cpp
|
||||
typedef struct {
|
||||
ElemType * elem;
|
||||
int front;
|
||||
int rear;
|
||||
int maxSize;
|
||||
ElemType * elem;
|
||||
int front;
|
||||
int rear;
|
||||
int maxSize;
|
||||
}SqQueue;
|
||||
```
|
||||
|
||||
@@ -1401,10 +1429,10 @@ Sequence table data structure and pictures
|
||||
|
||||
```cpp
|
||||
typedef struct {
|
||||
ElemType *elem;
|
||||
int length;
|
||||
int size;
|
||||
int increment;
|
||||
ElemType *elem;
|
||||
int length;
|
||||
int size;
|
||||
int increment;
|
||||
} SqList;
|
||||
```
|
||||
|
||||
@@ -1484,14 +1512,14 @@ Hash table data structure and pictures for linear detection
|
||||
typedef char KeyType;
|
||||
|
||||
typedef struct {
|
||||
KeyType key;
|
||||
KeyType key;
|
||||
}RcdType;
|
||||
|
||||
typedef struct {
|
||||
RcdType *rcd;
|
||||
int size;
|
||||
int count;
|
||||
bool *tag;
|
||||
RcdType *rcd;
|
||||
int size;
|
||||
int count;
|
||||
bool *tag;
|
||||
}HashTable;
|
||||
```
|
||||
|
||||
@@ -1836,12 +1864,12 @@ For non-threaded systems:
|
||||
#### Communication between processes and advantages and disadvantages
|
||||
|
||||
* Pipeline (PIPE)
|
||||
* Famous Pipeline: A half-duplex communication method that allows communication between unrelated processes
|
||||
* Named pipes: A first-in-first-out communication method that allows communication between unrelated processes
|
||||
* Advantages: can achieve inter-process communication in any relationship
|
||||
* Disadvantages:
|
||||
1. Long-term storage in the system, improper use is prone to errors
|
||||
Limited buffer
|
||||
* Unnamed pipe: a half-duplex communication method that can only be used between processes with parental relationships (parent-child processes)
|
||||
* Anonymous pipes: A simplex first-in-first-out communication method that can only be used between processes with affinity (parent-child processes)
|
||||
* Advantages: simple and convenient
|
||||
* Disadvantages:
|
||||
Limited to one-way communication
|
||||
@@ -2010,14 +2038,14 @@ using namespace std;
|
||||
|
||||
int main()
|
||||
{
|
||||
int i = 0x12345678;
|
||||
int i = 0x12345678;
|
||||
|
||||
if (*((char*)&i) == 0x12)
|
||||
cout << "Big endian" << endl;
|
||||
else
|
||||
cout << "Little endian" << endl;
|
||||
if (*((char*)&i) == 0x12)
|
||||
cout << "Big endian" << endl;
|
||||
else
|
||||
cout << "Little endian" << endl;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -2156,7 +2184,7 @@ application:
|
||||
#### Interior Gateway Protocol
|
||||
|
||||
* RIP (Routing Information Protocol, Routing Information Protocol)
|
||||
* OSPF (Open Sortest Path First)
|
||||
* OSPF (Open Shortest Path First)
|
||||
|
||||
#### External gateway protocol
|
||||
|
||||
@@ -2203,7 +2231,7 @@ Port number | 21 | 23 | 25 | 53 | 69 | 80 | 443 | 161
|
||||
|
||||
Feature:
|
||||
* Connection oriented
|
||||
* Only point-to-point (one-to-one) communication
|
||||
* End-to-end communication
|
||||
* Reliable interaction
|
||||
* Full-duplex communication
|
||||
* Byte stream oriented
|
||||
@@ -2651,7 +2679,7 @@ So there is a FIN and ACK in each direction.
|
||||
* Basic lock types: exclusive lock (X lock / write lock), shared lock (S lock / read lock).
|
||||
* Livelock deadlock:
|
||||
* Livelock: The transaction is always in a waiting state, which can be avoided through a first come, first served policy.
|
||||
* Deadlock: Things can never end
|
||||
* Deadlock: The transaction can never end
|
||||
* Prevention: one-time block method, sequential block method;
|
||||
* Diagnosis: timeout method, waiting graph method;
|
||||
* Cancel: Undo the transaction with the least deadlock cost and release all the locks of this transaction, so that other transactions can continue to run.
|
||||
@@ -3387,7 +3415,7 @@ contain:
|
||||
|
||||
## 📝 Interview Question Experience
|
||||
|
||||
* [Newcoder.com's summary of the 2020 autumn tricks! (Post division)](https://www.nowcoder.com/discuss/205497)
|
||||
* [Nowcoder.com's summary of the 2020 autumn tricks! (Post division)](https://www.nowcoder.com/discuss/205497)
|
||||
* [【Preparation for Autumn Moves】 Raiders for 2020 Autumn Moves](https://www.nowcoder.com/discuss/197116)
|
||||
* [2019 School Recruitment Summary! 【Daily Update】](https://www.nowcoder.com/discuss/90907)
|
||||
* [2019 School Recruitment Technology Posts Summary [Technology]](https://www.nowcoder.com/discuss/146655)
|
||||
@@ -3395,8 +3423,8 @@ contain:
|
||||
* [2017 Autumn Campus Recruitment Pen and Face Summaries](https://www.nowcoder.com/discuss/12805)
|
||||
* [The most complete collection of 2017 spring tricks in history!!](https://www.nowcoder.com/discuss/25268)
|
||||
* [Interview questions are here](https://www.nowcoder.com/discuss/57978)
|
||||
* [Knowing.. On the Internet job search, what well-written and attentive face have you seen? It is best to share your own facial and mental journey. ](https://www.zhihu.com/question/29693016)
|
||||
* [Know. What are the most common interview algorithm questions for internet companies? ](https://www.zhihu.com/question/24964987)
|
||||
* [zhihu. On the Internet job search, what well-written and attentive face have you seen? It is best to share your own facial and mental journey. ](https://www.zhihu.com/question/29693016)
|
||||
* [zhihu. What are the most common interview algorithm questions for internet companies? ](https://www.zhihu.com/question/24964987)
|
||||
* [CSDN. C ++ Interview Questions Completely Organized](http://blog.csdn.net/ljzcome/article/details/574158)
|
||||
* [CSDN. Baidu R & D interview questions (C ++ direction)](http://blog.csdn.net/Xiongchao99/article/details/74524807?locationNum=6&fps=1)
|
||||
* [CSDN. C ++ 30 common interview questions](http://blog.csdn.net/fakine/article/details/51321544)
|
||||
@@ -3410,7 +3438,7 @@ contain:
|
||||
|
||||
## 📆 Recruiting time posts
|
||||
|
||||
* [Niuke.com 2020 School Recruitment | 2020 IT Enterprise Recruitment Schedule](https://www.nowcoder.com/school/schedule)
|
||||
* [nowcoder . Enterprise Recruitment Schedule](https://www.nowcoder.com/school/schedule)
|
||||
|
||||
<a id="recommend"></a>
|
||||
|
||||
@@ -3431,4 +3459,4 @@ contain:
|
||||
|
||||
This repository follows the CC BY-NC-SA 4.0 (signed-non-commercial use-shared in the same way) agreement, please indicate the source when reprinting, and should not be used for commercial purposes.
|
||||
|
||||
[](https://github.com/huihut/interview/blob/master/LICENSE)
|
||||
[](https://github.com/huihut/interview/blob/master/LICENSE)
|
||||
Reference in New Issue
Block a user