Const 正确的函数参数
在 const
-correct 函数中,所有传递的参考参数都被标记为 const
,除非函数直接或间接地修改它们,防止程序员无意中改变他们不想改变的东西。这允许函数同时采用 const
和非 cv 限定的实例,反过来,当调用成员函数时,实例的 this
的类型为 const T*
,其中 T
是类的类型。
struct Example {
void func() { std::cout << 3 << std::endl; }
void func() const { std::cout << 5 << std::endl; }
};
void const_incorrect_function(Example& one, Example* two) {
one.func();
two->func();
}
void const_correct_function(const Example& one, const Example* two) {
one.func();
two->func();
}
int main() {
Example a, b;
const_incorrect_function(a, &b);
const_correct_function(a, &b);
}
// Output:
3
3
5
5
虽然它的效果不如 const
正确的类设计那么明显(因为 const
-correct 函数和 const
-不正确的类会导致编译错误,而 const
-正确的类和 const
-错误的函数将正确编译),const
正确函数将捕获许多错误,这些错误会导致错误的函数泄漏,例如下面的错误。 [注意,如果 const
不正确的函数在预期非 const
实例时传递了 const
实例,则会导致编译错误。]
// Read value from vector, then compute & return a value.
// Caches return values for speed.
template<typename T>
const T& bad_func(std::vector<T>& v, Helper<T>& h) {
// Cache values, for future use.
// Once a return value has been calculated, it's cached & its index is registered.
static std::vector<T> vals = {};
int v_ind = h.get_index(); // Current working index for v.
int vals_ind = h.get_cache_index(v_ind); // Will be -1 if cache index isn't registered.
if (vals.size() && (vals_ind != -1) && (vals_ind < vals.size()) && !(h.needs_recalc())) {
return vals[h.get_cache_index(v_ind)];
}
T temp = v[v_ind];
temp -= h.poll_device();
temp *= h.obtain_random();
temp += h.do_tedious_calculation(temp, v[h.get_last_handled_index()]);
// We're feeling tired all of a sudden, and this happens.
if (vals_ind != -1) {
vals[vals_ind] = temp;
} else {
v.push_back(temp); // Oops. Should've been accessing vals.
vals_ind = vals.size() - 1;
h.register_index(v_ind, vals_ind);
}
return vals[vals_ind];
}
// Const correct version. Is identical to above version, so most of it shall be skipped.
template<typename T>
const T& good_func(const std::vector<T>& v, Helper<T>& h) {
// ...
// We're feeling tired all of a sudden, and this happens.
if (vals_ind != -1) {
vals[vals_ind] = temp;
} else {
v.push_back(temp); // Error: discards qualifiers.
vals_ind = vals.size() - 1;
h.register_index(v_ind, vals_ind);
}
return vals[vals_ind];
}