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

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.

主站蜘蛛池模板: 芜湖市| 枝江市| 天气| 松原市| 吉林省| 体育| 盐边县| 化州市| 慈溪市| 兴文县| 鄂托克前旗| 且末县| 长乐市| 吉隆县| 安丘市| 巧家县| 萨迦县| 二连浩特市| 西华县| 建宁县| 贵德县| 文成县| 马关县| 河曲县| 池州市| 宁陵县| 西青区| 武穴市| 易门县| 乡宁县| 张掖市| 石家庄市| 莱州市| 金乡县| 永修县| 日照市| 海阳市| 诏安县| 汪清县| 阿巴嘎旗| 资溪县|