官术网_书友最值得收藏!

Const Parameters and Default Arguments

In the previous chapter, we saw how and when to use references in function parameters and return types. C++ has an additional qualifier, the const qualifier, which can be used independently from the ref-ness (whether the type is a reference or not) of the type.

Let's see how const is used in the various scenarios we investigated when looking at how functions can accept parameters.

Passing by const Value

In pass by value, the function parameter is a value type: when invoked, the argument is copied into the parameter.

This means that regardless of whether const is used in the parameter or not, the calling code cannot see the difference.

The only reason to use const in the function signature is to document to the implementation that it cannot modify such a value.

This is not commonly done, as the biggest value of a function signature is for the caller to understand the contract of calling the function. Because of this, it is rare to see int max(const int, const int), even if the function does not modify the parameters.

There is an exception, though: when the function accepts a pointer.

In such cases, the function wants to make sure that it is not assigning a new value to the pointer. The pointer acts similar to a reference here, since it cannot be bound to a new object, but provides nullability.

An example could be setValue(int * const), a function that takes a const pointer to an int.

The integer is not const, so it can be changed, but the pointer is const and the implementation cannot change it during implementation.

Passing by const Reference

Const is extremely important in pass by reference, and any time you use a reference in the parameters of a function, you should also add const to it (if the function is not designed to modify it).

The reason for this is that a reference allows you to modify the provided object freely.

It is error-prone, since the function might modify an object the caller does not expect to be modified by mistake, and it is hard to understand as there is no clear boundary between the caller and the function, again, because the function can modify the state of the caller.

const instead fixes the problem, since a function cannot modify an object through a const reference.

This allows the function to use reference parameters without some of the drawbacks of using references.

The function should remove the const from a reference, but only if it is intended to modify the provided object, otherwise every reference should be const.

Another advantage of const reference parameters is that temporary objects can be used as arguments for them.

Returning by const Value

There is no widespread reason to return by const value since the calling code often assigns the value to a variable, in which case the const-ness of the variables is going to be the deciding factor, or passes the value to a next expression, and it is rare for an expression to expect a const value.

Returning by const value also inhibits the move semantic of C++11, thus reducing performance.

Returning by const Reference

A function should always return by const reference when the returned reference is meant to only be read and not be modified by the calling code.

The same concept we applied to object lifetimes when returning references to them also apply to const:

  • When returning a reference accepted as a parameter, if the parameter is a const reference, the returned reference must be const as well
  • When returning a reference to a part of an object accepted as the const reference parameter, the returned reference must be const as well

A parameter accepted as a reference should be returned as a const reference if the caller is not expected to modify it.

Sometimes, the compilation fails, stating that the code is trying to modify an object that is a const reference. Unless the function is meant to modify the object, the solution is not to remove const from the reference in the parameter. Instead, look for why the operation that you are trying to perform does not work with const, and what the possible alternatives are.

const is not about the implementation, it is about the meaning of the function.

When you write the function signature, you should decide whether to use const, as the implementation will have to find a way to respect that.

For example:

void setTheThirdItem(std::array<int, 10>& array, int item)

This should clearly take a reference to the array since its purpose is to modify the array.

On the other hand, we can use the following:

int findFirstGreaterThan(const std::array<int, 10>& array, int threshold)

This tells us that we are only looking into the array – we are not changing it, so we should use const.

Note

It is a best practice to use const as much as possible, as it allows the compiler to make sure that we are not modifying objects that we do not want to modify.

This can help to prevent bugs.

It also helps to keep another best practice in mind: never use the same variable to represent different concepts. Since the variable cannot be changed, it is less natural to reuse it instead of creating a new one.

主站蜘蛛池模板: 辽宁省| 宜都市| 诏安县| 宿松县| 威海市| 湖北省| 湛江市| 灵川县| 湘乡市| 保靖县| 安福县| 石景山区| 德江县| 闸北区| 汾阳市| 错那县| 安达市| 峨边| 凉城县| 墨玉县| 新蔡县| 临西县| 三台县| 大丰市| 墨竹工卡县| 博白县| 泰州市| 德庆县| 榆中县| 建瓯市| 获嘉县| 罗田县| 尖扎县| 额济纳旗| 长顺县| 邢台县| 云和县| 洪湖市| 临清市| 华安县| 榆树市|