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

  • C++ Fundamentals
  • Antonio Mallia Francesco Zoffoli
  • 889字
  • 2021-06-11 13:36:00

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.

主站蜘蛛池模板: 长治县| 射阳县| 文水县| 彭水| 桐柏县| 麦盖提县| 郴州市| 建昌县| 栾川县| 万山特区| 霍州市| 玉山县| 沙洋县| 榕江县| 恭城| 呼玛县| 绩溪县| 黄石市| 荥经县| 冕宁县| 称多县| 博客| 木里| 四会市| 霍山县| 芮城县| 武强县| 秭归县| 黑河市| 西盟| 黔西县| 星子县| 呼玛县| 墨玉县| 深圳市| 商城县| 东乡| 沁阳市| 大埔区| 赣榆县| 楚雄市|