Skip to content

Commit 2e63a68

Browse files
committed
resolve changkun#17, fix wrong description and example for constexpr
1 parent a2c90ba commit 2e63a68

File tree

3 files changed

+15
-12
lines changed

3 files changed

+15
-12
lines changed

book/zh-cn/02-usability.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,24 +97,25 @@ int main() {
9797
// char arr_3[len]; // 非法
9898

9999
const int len_2 = len + 1;
100-
char arr_4[len_2]; // 合法
100+
constexpr int len_2_constexpr = 1 + 2 + 3;
101+
// char arr_4[len_2]; // 非法
102+
char arr_4[len_2_constexpr]; // 合法
101103

102104
// char arr_5[len_foo()+5]; // 非法
103105
char arr_6[len_foo_constexpr() + 1]; // 合法
104-
106+
105107
std::cout << fibonacci(10) << std::endl;
106108
// 1, 1, 2, 3, 5, 8, 13, 21, 34, 55
107-
109+
108110
return 0;
109111
}
110112
```
111113
112-
C++11 之前,可以在常量表达式中使用的变量必须被声明为 `const`,在上面代码中,`len_2` 被定义成了常量,因此 `len_2` 是一个常量表达式,所以能够合法的分配一个数组;而对于 `arr_5` 来说,C++98 之前的编译器无法得知 `len_foo()` 在运行期实际上是返回一个常数,这也就导致了非法的产生。
114+
上面的例子中,`char arr_4[len_2]` 可能比较令人困惑,因为 `len_2` 已经被定义为了常量。为什么 `char arr_4[len_2]` 仍然是非法的呢?这是因为 C++ 标准中数组的长度必须是一个常量表达式,而对于 `len_2` 而言,这是一个 `const` 常数,而不是一个常量表达式,因此(即便这种行为在大部分编译器中都支持,但是)它是一个非法的行为,我们需要使用接下来即将介绍的 C++11 引入的 `constexpr` 特性来解决这个问题;而对于 `arr_5` 来说,C++98 之前的编译器无法得知 `len_foo()` 在运行期实际上是返回一个常数,这也就导致了非法的产生。
113115
114116
> 注意,现在大部分编译器其实都带有自身编译优化,很多非法行为在编译器优化的加持下会变得合法,若需重现编译报错的现象需要使用老版本的编译器。
115117
116-
117-
C++11 提供了 `constexpr` 让用户显式的声明函数或对象构造函数在编译器会成为常数,这个关键字明确的告诉编译器应该去验证 `len_foo` 在编译期就应该是一个常数。
118+
C++11 提供了 `constexpr` 让用户显式的声明函数或对象构造函数在编译器会成为常量表达式,这个关键字明确的告诉编译器应该去验证 `len_foo` 在编译期就应该是一个常量表达式。
118119
119120
此外,`constexpr` 的函数可以使用递归:
120121
@@ -128,9 +129,9 @@ constexpr int fibonacci(const int n) {
128129

129130
```cpp
130131
constexpr int fibonacci(const int n) {
131-
if(n == 1) return 1;
132-
if(n == 2) return 1;
133-
return fibonacci(n-1) + fibonacci(n-2);
132+
if(n == 1) return 1;
133+
if(n == 2) return 1;
134+
return fibonacci(n-1) + fibonacci(n-2);
134135
}
135136
```
136137
@@ -232,7 +233,7 @@ public:
232233
int main() {
233234
// after C++11
234235
MagicFoo magicFoo = {1, 2, 3, 4, 5};
235-
236+
236237
std::cout << "magicFoo: ";
237238
for (std::vector<int>::iterator it = magicFoo.vec.begin(); it != magicFoo.vec.end(); ++it) std::cout << *it << std::endl;
238239
}

code/2/2.02.constexpr.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ int main() {
3838
// char arr_3[len]; // illegal
3939

4040
const int len_2 = len + 1;
41-
char arr_4[len_2]; // legal
41+
constexpr int len_2_constexpr = 1 + 2 + 3;
42+
// char arr_4[len_2]; // illegal, but ok for most of the compilers
43+
char arr_4[len_2_constexpr]; // legal
4244

4345
// char arr_5[len_foo()+5]; // illegal
4446
char arr_6[len_foo_constexpr() + 1]; // legal

code/2/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
all: $(patsubst %.cpp, %.out, $(wildcard *.cpp))
22

33
%.out: %.cpp Makefile
4-
clang++ $< -o $@ -std=c++17
4+
clang++ $< -o $@ -std=c++17 -pedantic
55

66
clean:
77
rm *.out

0 commit comments

Comments
 (0)