1.问题的关键是非 const 引用形参 (第 2.5 节) 只能与完全同类型的非 const 对象关联。
2.应该将不修改相应实参的形参定义为 const 引用。如果将这样的形参定义为非 const 引用,则毫无必要地限制了该函数的使用。例如,可编写下面的程序在一个 string 对象中查找一个指定的字符:
1 // returns index of first occurrence of c in s or s.size() if c isn't 2 in s 3 // Note: s doesn't change, so it should be a reference to const 4 string::size_type find_char(string &s, char c) 5 { 6 string::size_type i = 0; 7 while (i != s.size() && s[i] != c) 8 ++i; // not found, look at next character 9 return i; 10 }
这个函数将其 string 类型的实参当作普通(非 const)的引用,尽管函数并没有修改这个形参的值。 这样的定义带来的问题是不能通过字符串字面值来调用这个函数:
if (find_char("Hello World", 'o')) // ...
虽然字符串字面值可以转换为 string 对象,但上述调用仍然会导致编译失败。
3.在含有 return 语句的循环后没有提供 return 语句是很危险的,因为大部分的编译器不能检测出这个漏洞,运行时会出现什么问题是不确定的。
下面是示例代码
1 // Determine whether two strings are equal. 2 // If they differ in size, determine whether the smaller 3 // one holds the same characters as the larger one 4 bool str_subrange(const string &str1, const string &str2) 5 { 6 // same sizes: return normal equality test 7 if (str1.size() == str2.size()) 8 return str1 == str2; // ok, == returns bool 9 // find size of smaller string 10 string::size_type size = (str1.size() < str2.size()) 11 ? str1.size() : str2.size(); 12 string::size_type i = 0; 13 // look at each element up to size of smaller string 14 while (i != size) { 15 if (str1[i] != str2[i]) 16 return; // error: no return value 17 } 18 // error: control might flow off the end of the function without 19 a return 20 // the compiler is unlikely to detect this error 21 }
4.const 对象、指向 const 对象的指针或引用只能用于调用其 const 成员函数,如果尝试用它们来调用非 const 成员函数,则是错误的。
5.函数的重载与重复声明辨析:
1 // const is irrelevent for nonreference parameters 2 Record lookup(Phone); 3 Record lookup(const Phone); // redeclaration
《C++ Primer》中有这样两端段话:
“最后一对的区别仅在于是否将形参定义为 const。 这种差异并不影响传递至函数的对象; 第二个函数声明被视为第一个的重复声明。 其原因在于实参传递的方式。复制形参时并不考虑形参是否为 const——函数操纵的只是副本。 函数的无法修改实参。 结果, 既可将 const 对象传递给 const 形参, 也可传递给非 const 形参,这两种形参并无本质区别。”
“值得注意的是,形参与 const 形参的等价性仅适用于非引用形参。有 const 引用形参的函数与有非 const 引用形参的函数是不同的。类似地,如果函数带有指向 const 类型的指针形参, 则与带有指向相同类型的非 const 对象的指针形参的函数不相同。”
参考下面代码,有利于理解上面引号中的两段话:
1 const int ival = 1024; 2 const int &refVal = ival; // ok: both reference and object are 3 const 4 int &ref2 = ival; // error: non const reference to a 5 const object
另外,在VC++6.0中编译下段代码,编译通过,证明:const引用可以绑定到非const对象上
1 int ival = 1024; 2 const int &refVal = ival;
6.非 const 引用只能绑定到与该引用同类型的对象。
const 引用则可以绑定到不同但相关的类型的对象或绑定到右值。