C++ 学习笔记

当想要保护自己重要的人的时候,人就会变得很坚强。
——《火影忍者》白

常量指针 & 指针常量

实际上就是一个剥洋葱的过程,从内到外逐步剥开:

1
2
const int * p; // p -> p 是指针 -> p 指向 int -> 这个 int 不可变 => 常量指针
int * const p; // p -> p 不可变 -> p 是指针 -> p 指向 int => 指针常量

top-level const 和 low-level const

C++ Primer 中对 top-level const 和 low-level const 解释得非常模糊,翻译上也很容易造成误导。top-level const 翻译成 “顶层 const” 没问题,但 low-level const 就不该翻译成 “底层 const” 了,这让 bottom-level const 情何以堪?

看了一圈,还是 Stack Overflow 上的一个回答直击本质:

使得被修饰的变量本身无法改变的 const 是 top-level const,其他的通过指针或引用等间接途径来限制目标内容不可变的 const 是 low-level const。

现在再看书上的注释就好懂了吧:

C++ Primer Edition 5th P62
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int i = 0, &r = i;
auto a = r;
const int ci = i, &cr = ci;
auto b = ci;
auto c = cr;
auto d = &i;
auto e = &ci;
const auto f =ci;
auto &g = ci;
auto &h = 42;
const auto &j =42;
auto &m = ci;
auto *p = &ci;
auto &n = i, *p2 = &ci; // Wrong!

类内静态成员的初始化

虽然 C++ 新标准已经支持 in-class initializer,但如果等号右边不是常量表达式(比如要调用函数计算),还是需要使用传统 类内定义,类外初始化 的技术

1
2
3
4
5
class calc{
private:
static const double t; // 类内定义
};
const double calc::t = atan(2); // 类外初始化,注意不要加 static

简单的常量表达式,使用 enum 定义会更优雅:

1
2
3
4
class calc{
private:
enum { TOTAL = 10 }; // so elegant!
};

如果是 Java,在 static 块里初始化就好了。

开发环境配置

vscode 关闭 C++ 11 Warning

首先,在你用的查错插件里将 C++ 版本换为 C++17,我用的 C/C++ Clang Command Adapter,只要在 Clang: Cxxflags 一栏添加 -std=C++17 即可。

然后,关掉用 Coderunner 一键运行时终端里的警告。打开 settings.json, 在 "code-runner.executorMap" 对应 C++ 的一项里加入 -std=c++17 即可。

settings.json
1
"cpp": "cd $dir && clang++ -std=c++17 $fileName -o $fileNameWithoutExt && $dir$fileNameWithoutExt",

最后,关掉调试时的警告。在 tasks.json 的运行参数中加入 "-std=c++17" 即可。

tasks.json
1
2
3
4
5
6
7
"args": [
"${fileBasename}",
"-o",
"${fileBasenameNoExtension}",
"-g",
"-std=c++17", // 加在这里
],

Jupyter 安装 C++ Kernel

安装 Xeus-Cling Kernel 让我们也能在 Jupyter 上愉快地写 C++。我用的 pyenv 管理 Python 版本,所以先切换到 miniconda 环境,用 conda 新建一个环境来装 Xeus-Cling。注意,根据官方教程只能用 miniconda,而不能用 anaconda。

1
2
3
4
5
6
pyenv local miniconda3-4.7.12 # 切换到 miniconda
conda create -n cpp # 为 xeus-cling 创建名为 cpp 的虚拟环境
conda activate cling # 切换到新创建的 cpp 环境
conda install jupyter notebook # 为新环境安装 jupyter
conda install xeus-cling -c conda-forge # 安装 xeus-cling 内核
jupyter kernelspec list # 查看所有安装的 kernel

如果 xcpp11xcpp14xcpp17 都有显示,则说明已经安装成功

1
2
3
4
5
Available kernels:
python3 /Users/stardust/.pyenv/versions/miniconda3-4.7.12/envs/cling/share/jupyter/kernels/python3
xcpp11 /Users/stardust/.pyenv/versions/miniconda3-4.7.12/envs/cling/share/jupyter/kernels/xcpp11
xcpp14 /Users/stardust/.pyenv/versions/miniconda3-4.7.12/envs/cling/share/jupyter/kernels/xcpp14
xcpp17 /Users/stardust/.pyenv/versions/miniconda3-4.7.12/envs/cling/share/jupyter/kernels/xcpp17

打开 jupyter notebook ,看看是不是已经可以写 C++ 了。