总结与测验
本章内容广泛,你已顺利完成,表现出色!
复合语句(或称语句块)是由零条或多条语句组成的整体,编译器将其视为单条语句。语句块以左花括号“{”开始,以右花括号“}”结束,中间放置待执行的语句。凡允许出现单条语句之处,皆可使用语句块;语句块结尾无需分号。语句块常与 if
语句配合使用,以实现多条语句的批量执行。
用户自定义命名空间系由程序员自行定义的命名空间,用于容纳自定义声明。C++ 自身提供的命名空间(如全局命名空间)或库提供的命名空间(如命名空间 std
)均不属于用户自定义命名空间。
可通过作用域解析运算符(::
)访问某命名空间内的声明。该运算符告知编译器,应在左侧操作数指定的作用域中查找右侧操作数所标识的符号;若左侧操作数缺省,则默认为全局命名空间。
局部变量系指在函数内部(含形参)定义的变量。局部变量具有块作用域,即自其定义之处起,直至所属语句块结束,均处于有效作用域内。局部变量采用自动存储期:在定义点创建,在所属语句块结束时销毁。
嵌套语句块中声明的名称可遮蔽(屏蔽)外层语句块中同名变量,应避免此种情况。
全局变量系指在所有函数外部定义的变量。全局变量具有文件作用域,即自其声明之处起,直至所在文件结束,均可见。全局变量采用静态存储期:程序启动时创建,程序结束时销毁。应尽可能避免对静态变量进行动态初始化。
标识符的链接属性决定其他同名声明是否指向同一实体。局部变量无链接;具有内部链接的标识符仅可在单个文件内部可见并可用,其他文件无法访问;具有外部链接的标识符既可在定义文件内部可见并可用,亦可通过前置声明在其他代码文件中使用。
应尽可能避免使用非常量全局变量;常量全局变量通常可接受。若编译器支持 C++17,可使用 inline
变量定义全局常量。
可在局部变量前加 static
关键字,使其获得静态存储期。
限定名称系指包含作用域限定符的名称(如 std::string
);非限定名称则不含作用域限定符(如 string
)。
using
语句(含 using
声明与 using
指令)可避免显式命名空间限定。using
声明允许将非限定名称作为限定名称的别名;using
指令则将某命名空间的所有标识符导入当前作用域。二者一般均应慎用。
内联展开系指用被调用函数的定义代码取代函数调用的过程。以 inline
关键字声明的函数称为内联函数。
内联函数与内联变量须满足两项主要要求:
- 在每个使用该函数的翻译单元中,编译器必须能够看见其完整定义(仅前置声明不足);若同时提供前置声明,定义可位于使用点之后。
- 所有内联函数或变量的定义必须完全一致,否则将导致未定义行为。
在现代 C++ 中,“inline”一词已演化为“允许多次定义”。因此,内联函数指可在多个文件中定义的函数。C++17 引入内联变量,指可在多个文件中定义的变量。
内联函数与内联变量尤其适用于仅含头文件的库,此类库由若干头文件实现功能,不涉及 .cpp
文件。
最后,C++ 支持无名命名空间,其内部所有内容隐式拥有内部链接;亦支持内联命名空间,可为命名空间提供初级的版本管理功能。
测验
问题 #1
修正以下程序:
#include <iostream>
int main()
{
std::cout << "Enter a positive number: ";
int num{};
std::cin >> num;
if (num < 0)
std::cout << "Negative number entered. Making positive.\n";
num = -num;
std::cout << "You entered: " << num;
return 0;
}
问题 #2
编写一个名为 constants.h
的头文件,使下列程序能够编译运行。若编译器支持 C++17,请使用 inline constexpr
变量;否则使用普通 constexpr
变量。maxClassSize
的值应为 35。
main.cpp:
#include "constants.h"
#include <iostream>
int main()
{
std::cout << "How many students are in your class? ";
int students{};
std::cin >> students;
if (students > Constants::maxClassSize)
std::cout << "There are too many students in this class";
else
std::cout << "This class isn't too large";
return 0;
}
问题 #3
编写函数 int accumulate(int x)
。该函数应返回所有已传入 x
值的总和。
提示:
下列程序应能编译运行,并按注释所示输出结果:
#include <iostream>
int main()
{
std::cout << accumulate(4) << '\n'; // prints 4
std::cout << accumulate(3) << '\n'; // prints 7
std::cout << accumulate(2) << '\n'; // prints 9
std::cout << accumulate(1) << '\n'; // prints 10
return 0;
}
3b) 附加题
上述 accumulate()
函数存在哪两个缺陷?