Why are C ++ operator indices often paired?

The C ++ FAQ defines a Matrix container container to avoid the complicated new delete code. Does the tutorial say that index operators often fall in pairs? Why is this so?

 T& operator() (unsigned i, unsigned j); T const& operator() (unsigned i, unsigned j) const; 

Why is this so?

This is also called: const-overloading.

FAQ gives hints. Do you have additional comments?

In particular, should mutate() follow certain rules that should only be used safely for const objects?

+4
source share
2 answers

Calling the index operator on the T& object, the first non-constant operator is called. Then the operations are checked and changed.

Calling the index operator on the object T const & , the second operator const is called. Verification is then allowed, but mutation is not allowed.

Example here

 void f(MyFredList const& a) ← the MyFredList is const { // Okay to call methods that DON'T change the Fred at a[3]: Fred x = a[3]; a[3].inspect(); // Error (fortunately!) if you try to change the Fred at a[3]: Fred y; a[3] = y; ← Fortunately(!) the compiler catches this error at compile-time a[3].mutate(); ← Fortunately(!) the compiler catches this error at compile-time } 

C ++ Credits FAQ, more here .

+2
source

Simply put, because there are two sides to the destination: left and right.

Non-envelope version: T& operator() (unsigned i, unsigned j); intended primarily for the left side of the assignment (that is, for use as a destination)

Version const: T const& operator() (unsigned i, unsigned j) const; Designed exclusively for the right side of the assignment.

Note the difference in the wording there: the const version can be used only on the right side of the destination, while the version without a constant can be used on both sides. If, however, you have a const -qualified object, you can only call functions defined with const, so you cannot use it at all in this case. This is exactly what you (at least usually) want - it prevents the modification of the object you said should not be changed (using const-qualifying it).

As for mutate , it is usually used only for objects that have some difference between their logical state and their bit-muddy state. A common example is a class that does some (usually expensive) calculations lazily. To avoid recalculating the value, it saves the value after calculating it:

 class numbers { std::vector<double> values; mutable double expensive_value; bool valid; public: numbers() : valid(false) {} double expensive_computation() const { if (valid) return expensive_value; // compute expensive_value here, and set `valid` to true } }; 

So, the result from expensive_computation depends only on the values ​​in values . If you don't need speed, you can simply recalculate the value each time the user is called expensive_computation . Calling it repeatedly in a const object will always give the same result, although, therefore, by calling it once, we assume that it can be called again, and in order not to repeat the same expensive calculation repeatedly, we simply store the value in expensive_value . Then, if the user requests it again, we simply return the value.

In other words, from a logical point of view, the object remains const , even if / if we change the expensive_value . The visible state of the object does not change. All we did was let him complete const tasks faster.

For this to work correctly, we would also like to set valid back to false anytime the user changes the contents of values . For instance:

 void numbers::add_value(double new_val) { values.push_back(new_val); valid = false; } 

In some cases, we may also need an intermediate level of certainty - we could calculate an expensive_value faster (for example), knowing exactly which numbers were added to the values , and not just having a logical value to say whether it is valid or not.

I must add that C ++ 11 adds some new requirements to both const and mutable . In short, in most cases you need to ensure that everything that is const and / or mutable also thread safe. You can watch the Herb Sutter video. However, I feel obligated to add that, in my opinion, his conclusion is relatively mutable , probably a little exaggerated (but I would rather you watch and decide on your own than a word for that).

+7
source

Source: https://habr.com/ru/post/1469543/


All Articles