图 5.8典型的按值调用分析
图 5.9典型的用指针参数按引用调用分析
5.5 指针与常量限定符
const限定符可以使程序员告诉编译器特定变量的值不能修改。 软件工程视点5. 1
const限定符可以执行最低权限原则。利用最低权限原则正确设计软件可以大大减少调试时间和不正确的副作用,使程序更容易修改与维护。 可移植性提示5.2
尽管ANSI C和C++中定义了const定符,但有些编译器无法正确实现。 几年来,大量C语言遗留代码都是在没有const限定符的情况下编写的。因此,使用旧版C语言代码的软件工程有很大的改进空间。许多目前使用ANSI C和C++的程序员也没有在程序中使用const限定符,因为他们是从C语言的早期版本开始编程的,这些程序员错过了许多改进软件工程的好机会。
函数参数使用或不用const限定符的可能性有六种,两种用按值调用传递参数,四种按引用调用传递参数,根据最低权限原则来进行选择。在参数中向函数提供完成指定任务所需的数据访问,但不要提供更多权限。
第3章曾经介绍,按值调用传递参数时,函数调用中要生成参数副本并将其传递给函数。如果函数中修改副本,则调用者的原值保持不变。许多情况下,需要修改传入函数的值以使函数能够完成任务。但有时即使被调用函数只是操作原值的副本,也不能在被调用函数中修改这个值。
假设函数取一个单下标数组及其长度为参数,并打印数值。这种函数应对数组进行循环并分别输出每个数组元素。函数体中用数组长度确定数组的最高下标,以便在打印完成后结束循环。在函数体中不能改变这个数组长度。 软件工程视点5.2
如果函数体中不能修改传递的值,则这个参数应声明为const以避免被意外修改。
如果试图修改const类型的值,则编译器会捕获这个错误并发出一个警告或错误消息(取决于特定的编译器)。 轶件工程视点5.3
按值调用时,只舱在调用函数中改变一个值。这个值通过函数返回值进行赋值。要在调用函数中改变多个值,就要按引用传递多个参数。 编程技巧5.3
使用函数之前,检查函数原型以确定可以修改的参数。
将指针传递给函数有四种方法:非常量数据的非常量指针、常量数据的非常量指针、非常量数据的常量指针和常量数据的常量指针。每种组合提供不同的访问权限。
最高访问权限是非常量数据的非常量指针,可以通过复引用指针而修改,指针可以修改成指向其他数据。声明非常量数据的非常量指针时不用const。这种指针可以接收函数中的字符串,用指针算法处理或修改字符串中的每个字符。图5.10中的函数convertToUppercase声明参数sPtr(char*sPtr)为非常量数据的非常量指针。函数用指针算法一次一个字符地处理字符串string。字符串中,st到,x,的字符用函数toupper变为相应的大写字母,其余字符不变。函数toupper取一个字符作为参数。
如果是小写字母,则返回相应的大写字母,否则返回原字符。函数toupper是字符处理库ctype.h中(见第16章)的一部分。
常量数据的非常量指针,指针可以修改成指向其他数据,但数据不能通过指针修改。这种指针可以接收函数的数组参数,函数处理数组每个元素而不修改数据。例如,图5.1l的函数printCharacters将参数sPtr声明为const char*类型.表示“sPtr是字符常量的指针”。函数体用for循环输出字符串中的每个字符,直到遇到null终止符。打印每个字符之后,指针sPtr递增,指向字符串中下一个宇符。
1 // Fig. 5.10: fig0510.cpp
2 // Converting lowercase letters to uppercase letters 3 // using a non-constant pointer to non-constant data 4 #include
7 void convertToUppercase( char * ); 8
9 int main() 10 {
11 char string[] = \12
13 cout << \14 convertToUppercase( string );
15 cout << \16 cout << string << endl; 17 return 0; 18 } 19
20 void convertToUppercase{ char *sPtr ) 21 {
22 while ( *sPtr != '\\0' ) { 23
24 if (*sPtr >= 'a' && *sPtr <= 'z' )
25 *sPtr = toupper( *sPtr ); // convert to uppercase 26
27 ++sPtr; // move sPtr to the next character 28 } 29 }
输出结果:
The string before conversion is: characters and $32.98 The string after conversion is: CHARACTERS AND $32.98
图5.10将字符串变成大写
1 // Fig. 5.11:fig05 ll.cpp
2 // Printing a string one character at a time using 3 // a non-constant pointer to constant data 4 #include
6 void printCharacters( const char * ); 7
8 int main() 9 {
10 char string[] = \11
12 cout << \13 printCharacters( string ); 14 cout << endl; 15 return 0; 16 } 17
18 // In printCharacters, sPtr is a pointer to a character 19 // constant. Characters cannot be modified through sPtr 20 // (i.e., sPtr is a \21 void printCharacters( const char *sPtr ) 22 {
23 for ( ; *sPtr != '\\0'; sPtr++ ) // no initialization 24 cout << *sPtr; 25 }
输出结果: The string is:
print characters of a string
图5.11 用常量数据的非常量指针打印字符串(一次打印一个字符)
图5.12演示了函数接收常量数据的非常量指针,并试图通过指针修改数据在编译时产生的语法错误消息。
1 // Fig. 5.12: fig05_12.cpp
2 // Attempting to modify data through a 3 // non-constant pointer to constant data. 4 #include
6 void f( const int* ); 7
8 int main() 9 {
10 int y; 11
12 f( &y ); // f attempts illegak modification 13
14 return 0; 15 }