Skip to content

Commit

Permalink
去除文件空格,添加一些 README 文件,创建 SUMMARY 文件以支持 GitBook
Browse files Browse the repository at this point in the history
  • Loading branch information
Mq-b committed Mar 17, 2024
1 parent 630f9aa commit 1d6f890
Show file tree
Hide file tree
Showing 7 changed files with 293 additions and 246 deletions.
23 changes: 23 additions & 0 deletions SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Summary

* [作业与解析](README.md)
* [C++CoreGuidelines](src/C++CoreGuidelines/README.md)
- [第一章-简介](src/C++CoreGuidelines/第1章-简介.md)
- [第二章-理念](src/C++CoreGuidelines/第2章-理念.md)
- [第三章-接口](src/C++CoreGuidelines/第3章-接口.md)
- [第四章-函数](src/C++CoreGuidelines/第4章-函数.md)
- [第五章-类和类层次结构](src/C++CoreGuidelines/第5章-类和类层次结构.md)
* [卢瑟日经](src/卢瑟日经/README.md)
- [赋值运算符求值顺序的问题](src/卢瑟日经/赋值运算符求值顺序问题.md)
- [函数调用禁止隐式转换](src/卢瑟日经/函数调用禁止隐式转换.md)
- [数组&指针](src/卢瑟日经/数组&指针.md)
- [同步、异步、阻塞](src/卢瑟日经/同步、异步、阻塞.md)
- [为什么优先成员初始化器](src/卢瑟日经/为什么优先成员初始化器.md)
- [重载operator=要不要检查自赋值?](src/卢瑟日经/重载operator=要不要检查自赋值?.md)
- [C&C++伪规则和错误的看法](src/卢瑟日经/C&C++伪规则和错误的看法.md)
- [catch(auto)的问题](src/卢瑟日经/catch(auto)的问题.md)
- [detach的问题](src/卢瑟日经/detach的问题.md)
* [基础性C++题目与答案](src/基础性C++题目/README.md)
- [20231002 基础C++题目](src/基础性C++题目/20231002基础C++题目.md)
- [20231017基础C++题目(转换的使用)](src/基础性C++题目/20231017基础C++题目(转换的使用).md)
- [20231126基础C++题目(数组退化)](src/基础性C++题目/20231126基础C++题目(数组退化).md)
4 changes: 2 additions & 2 deletions src/C++CoreGuidelines/第2章-理念.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
理念性规则概览:

- [理念](#理念)
+ [P.1 在代码中直接表达思想](#p1-在代码中直接表达思想)
+ [P.1 在代码中直接表达思想](#p1-在代码中直接表达思想)
+ [P.2 用 ISO 标准写代码](#p2-用-iso-标准写代码)
+ [P.3 表达意图](#p3-表达意图)
+ [P.4 理想情况下,程序应该是静态类型安全的](#p4-理想情况下程序应该是静态类型安全的)
Expand All @@ -31,7 +31,7 @@

> 如果觉得没听懂不用在意,的确有点抽象,可以简单理解为一般情况下的编码规范。
## <span id="P1">P.1 在代码中直接表达思想</span>
## <span id="P1">P.1 在代码中直接表达思想</span>

编译器是不会去读注释(或设计文档)的,许多程序员也(固执地)不去读它们。 而代码中所表达的东西是带有 **明确的语义** 的,并且(原则上)是可以由编译器和其他工具进行检验的。

Expand Down
15 changes: 15 additions & 0 deletions src/卢瑟日经/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# 卢瑟日经

一些常见的卢瑟问题。

**目录一览**

- [赋值运算符求值顺序的问题](赋值运算符求值顺序问题.md)
- [函数调用禁止隐式转换](函数调用禁止隐式转换.md)
- [数组&指针](数组&指针.md)
- [同步、异步、阻塞](同步、异步、阻塞.md)
- [为什么优先成员初始化器](为什么优先成员初始化器.md)
- [重载operator=要不要检查自赋值?](重载operator=要不要检查自赋值?.md)
- [C&C++伪规则和错误的看法](C&C++伪规则和错误的看法.md)
- [catch(auto)的问题](catch(auto)的问题.md)
- [detach的问题](detach的问题.md)
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
# 20231002 基础 C++题目

## 题目

下面展示的代码

```C++
#include <iostream>

struct foo{
char a[16];
};

int main(){
foo a {"Hello, World!"};
auto b = a;
a.a[0] = '\0';
std::cout << b.a;
}
```

其行为是:

- A. 无法编译/未定义行为
- B. 可编译,保证无输出
- C. 可编译,保证输出`"Hello, World!"`
- D. 可编译,输出为实现定义

## 答案

C

## 解析

虽然数组类型不能直接赋值,但是作为类类型成员的数组类型,默认复制赋值函数的行为是逐元素复制。

- 此赋值行为在 C 语言也是成立的。
- 切忌将 foo::a 理解成指针。
# 20231002 基础 C++题目

## 题目

下面展示的代码

```C++
#include <iostream>

struct foo{
char a[16];
};

int main(){
foo a {"Hello, World!"};
auto b = a;
a.a[0] = '\0';
std::cout << b.a;
}
```

其行为是:

- A. 无法编译/未定义行为
- B. 可编译,保证无输出
- C. 可编译,保证输出`"Hello, World!"`
- D. 可编译,输出为实现定义

## 答案

C

## 解析

虽然数组类型不能直接赋值,但是作为类类型成员的数组类型,默认复制赋值函数的行为是逐元素复制。

- 此赋值行为在 C 语言也是成立的。
- 切忌将 foo::a 理解成指针。
Original file line number Diff line number Diff line change
@@ -1,69 +1,69 @@
# 20231017 基础 C++题目

## 题目

### 1. 下面展示的代码应当使用

```C++
struct Base { int x; };
struct Derived : Base { int y; }

int get_xy(Base * param){
auto pd = ????_cast<Derived*>(param);
return pd->x * pd->y;
}
```
- A. static_cast
- B. dynamic_cast
- C. 以上全部
- D. 不允许转换
### 2. 下面展示的代码应当使用
```C++
void erased_call(void (* pfn)(void), const char * param){
auto typed_pfn = ????_cast<void(*)(const char *)>(pfn);
typed_pfn(param);
}
```

- A. static_cast
- B. reinterpret_cast
- C. 以上全部
- D. 不允许转换

### 3. 下面展示的代码应当使用

```C++
template<typename T>
void foo(T&& i){
// some implemetion code
}

void speciallized_foo(int param){
auto spfoo = ????_cast<void(*)(const double&)>(foo);
spfoo(param);
}
```
- A. static_cast
- B. reinterpret_cast
- C. 以上全部
- D. 不允许转换
## 答案
1. A
2. B
3. A
## 解析
1. 此处 `Base` 并非多态类型,因此 `dynamic_cast` 无法进行基类指针到派生类指针的转换,而 `static_cast` 可以,[如](https://godbolt.org/z/8nGEvPTE8)。
+ 你可以为 `Base` 添加虚函数成员,使其成为多态类型,此时`dynamic_cast` 可以用于基类到派生类的转换。
+ 注意 `static_cast` 并不像 `dynamic_cast` 那样具有 [RTTI](https://zh.wikipedia.org/zh-hans/%E5%9F%B7%E8%A1%8C%E6%9C%9F%E5%9E%8B%E6%85%8B%E8%A8%8A%E6%81%AF) ,无法转换时不会返回 `nullptr` 或抛出异常。通过不合法的转换得到的指针去访问成员会产生[未定义行为](https://zh.cppreference.com/w/cpp/language/ub)。
2. `reinterpret_cast`可以用于函数指针的转换,而 `static_cast` 不可以。
+ 此处 `reinterpret_cast` 并不会产生实际转换代码。
+ 普通指针 `void *` 和函数指针 `void (*)(void)` 在一些平台上的长度不同,C++ 标准并不保证这两种类型能够以 `reinterpret_cast` 互相转换。
3. 进行 `static_cast` 转换的时候会发生重载决议,模板函数会实例化为选择到的函数类型,再隐式转换为函数指针。
# 20231017 基础 C++题目

## 题目

### 1. 下面展示的代码应当使用

```C++
struct Base { int x; };
struct Derived : Base { int y; }

int get_xy(Base * param){
auto pd = ????_cast<Derived*>(param);
return pd->x * pd->y;
}
```
- A. static_cast
- B. dynamic_cast
- C. 以上全部
- D. 不允许转换
### 2. 下面展示的代码应当使用
```C++
void erased_call(void (* pfn)(void), const char * param){
auto typed_pfn = ????_cast<void(*)(const char *)>(pfn);
typed_pfn(param);
}
```

- A. static_cast
- B. reinterpret_cast
- C. 以上全部
- D. 不允许转换

### 3. 下面展示的代码应当使用

```C++
template<typename T>
void foo(T&& i){
// some implemetion code
}

void speciallized_foo(int param){
auto spfoo = ????_cast<void(*)(const double&)>(foo);
spfoo(param);
}
```
- A. static_cast
- B. reinterpret_cast
- C. 以上全部
- D. 不允许转换
## 答案
1. A
2. B
3. A
## 解析
1. 此处 `Base` 并非多态类型,因此 `dynamic_cast` 无法进行基类指针到派生类指针的转换,而 `static_cast` 可以,[如](https://godbolt.org/z/8nGEvPTE8)。
+ 你可以为 `Base` 添加虚函数成员,使其成为多态类型,此时`dynamic_cast` 可以用于基类到派生类的转换。
+ 注意 `static_cast` 并不像 `dynamic_cast` 那样具有 [RTTI](https://zh.wikipedia.org/zh-hans/%E5%9F%B7%E8%A1%8C%E6%9C%9F%E5%9E%8B%E6%85%8B%E8%A8%8A%E6%81%AF) ,无法转换时不会返回 `nullptr` 或抛出异常。通过不合法的转换得到的指针去访问成员会产生[未定义行为](https://zh.cppreference.com/w/cpp/language/ub)。
2. `reinterpret_cast`可以用于函数指针的转换,而 `static_cast` 不可以。
+ 此处 `reinterpret_cast` 并不会产生实际转换代码。
+ 普通指针 `void *` 和函数指针 `void (*)(void)` 在一些平台上的长度不同,C++ 标准并不保证这两种类型能够以 `reinterpret_cast` 互相转换。
3. 进行 `static_cast` 转换的时候会发生重载决议,模板函数会实例化为选择到的函数类型,再隐式转换为函数指针。
Loading

0 comments on commit 1d6f890

Please sign in to comment.