GURU Of The Week Terms 06: Using Const Correctly

zhaozj2021-02-08  353

Gotw # 06 Const-Correctness

Author: Herb Sutter

Translation: Kingofark

[Declaration]: This article takes the Guru of The Week column on www.gotw.ca website, and its copyright belongs to the original person. Translator Kingofark translated this article without the consent of the original person. This translation is only for self-study and reference, please read this article, do not reprint, spread this translation; people download this translation content, please delete its backup immediately after reading. Translator Kingofark is not responsible for people who violate the above two principles. This declaration.

Revision 1.0

GURU Of The Week Terms 06: Using Const Correctly

Difficulty: 6/10

(Always use constable as possible, but don't use too much to cause abuse. Which places should be used, which places should not be used? Here we list some or obvious or unknown examples.)

[problem]

Const is a powerful tool to write "security" code, as well as the optimization processing of the compiler. You should use it as much as possible ... But what do you mean by "as much as possible?"

Please do not rate the quality of this program, do not change its structure; this program is intentionally designed to illustrate the issues of this Territor. You can use it as long as you add or delete "const" in the appropriate place. (Additional questions: What is the incorrect result of the program that cannot be expected or cannot be compiled?

Class polygon {

PUBLIC:

POLYGON (): area _ (- 1) {}

Void AddPoint (const point pt) {

Invalidatearea ();

Points_.push_back (pt);

}

Point getPoint (const INT i) {

Return Points_ [I];

}

Int getnumpoints () {

Return Points_.size ();

}

Double getarea () {

IF (Area_ <0) // If it has not been calculated and saved yet,

Calcarea (); // then start now.

Return Area_;

}

Private:

Void invalidatearea () {area_ = -1;}

Void Calcarea () {

Area_ = 0;

Vector :: Iterator i;

For (i = Points_.begin (); i! = points_.nd (); i)

Area_ = / * some work * /;

}

Vector Points_;

Double Area_;

}

Polygon Operator (Polygon & lh, Polygon & rhs) {

POLYGON RET = LHS;

Int last = rhs.getnumpoints ();

For (int i = 0; i

Ret.Addpoint (rhs.getpoint (i));

Return Ret;

}

Void f (const polygon & poly) {

Const_cast (poly) .addpoint (Point (0,0));

}

Void G (Polygon & Const rPOLY) {rPOLY.Addpoint (Point (1, 1));

}

Void h (polygon * const ppoly) {

PPOLY-> AddPoint (Point (2, 2));

}

Int main () {

POLYGON POLY;

Const polygon cpol;

f (poly);

f (cpoly);

g (poly);

H (& poly);

}

[answer]

* Class Polygon {

PUBLIC:

POLYGON (): area _ (- 1) {}

Void AddPoint (const point pt) {

Invalidatearea ();

Points_.push_back (pt);

}

1. Because the Point object uses a pass value, it is declared that there is almost no oil and water, which will not have a significant impact on performance.

* Point getPoint (const INT i) {

Return Points_ [I];

}

2. With 1, the const value is not much, but it is easy to cause misunderstandings.

3. This member function should be defined as a Const member function because it does not change the status of the object.

4. (This point is a controversial proposed method) If the return type of the function is not a built-in type, it should usually declare its return type and declare to const. This makes the caller of the function because it enables the compiler to generate an error message when the function caller is attempting to modify the temporary amount, thereby achieving the purpose (for example, "poly.getpoint (i) = Point (2, 2); ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, In the following narrative, we will see that when the const polygon object in Operator (), get getPoint () returns a const value or constant reference is also useful.).

[Author ": Lakos (PG.618) dissent against return constant values. He believes that the built-in type also returns a const value not only there is nothing practical, but it will also affect the physicalization process of the template. ]

[Learning Guidance]: When using a value returns a value returns a value of Non-Built-in, it is best to return a constant value when returning (return-by-value).

* Int getNumpoints () {

Return Points_.size ();

}

5. Or that sentence, the function itself should be declared as const.

(Note You should not return Const Int here, because int itself is already a right type; plus constant will affect the physicalization process of the template, so that the code is easy to make people confused, misunderstood, even It is also possible to indigestize.)

* Double getarea () {

IF (Area_ <0) // If it has not been calculated and saved yet,

Calcarea (); // then start now.

Return Area_;

}

6. Although this function modifies the internal state of the object, it should still be declared as const, because the visible object of the object has not changed (what we do is some hidden, no more conceited things, But this is a detail in the implementation, that is, this object is logically still constative. This means that Area_ should be declared into mutable. If your compiler does not support Mutable keywords, you can take const_cast operations to use the const_cast operation as an alternative (it is best to write a comment here so that you can replace this CAST operation when you can use the Mutable keyword. Drop.), But remember must let the function itself is declared as const.

* Private:

Void invalidatearea () {area_ = -1;}

7. Although this point of view is also controversial, I still insist that even if it is just a consider, I should still declare this function as const. (Of course, I have to admit that from the perspective of semantics, this function will only be called by the non-const function, because after all, its purpose just wants to save the saved Area_ value when the object is changed.)

* Void cagcarea () {

Area_ = 0;

Vector :: Iterator i;

For (i = Points_.begin (); i! = points_.nd (); i)

Area_ = / * some work * /;

}

8. This member function should definitely be constant. In any case, it will be called at least a CONST member function.

9. Since Iterator does not change the status of the Points_ set, this should be a const_iterator.

* Vector Points_;

Double Area_;

}

Polygon Operator (Polygon & lh, Polygon & rhs) {

10. Obviously, here should be passed through the Const reference (Reference).

11. Or that sentence, the return value should be constant.

* POLYGON RET = LHS;

Int last = rhs.getnumpoints ();

12. Since "Last" will never be changed, then it should also be "const int" type.

(This is also getPoint () - whether it returns a const value or const reference - must be a constant function.)

* Return Ret;

}

Void f (const polygon & poly) {

Const_cast (poly) .addpoint (Point (0,0));

Additional points: If the referenced object is declared as const, the results here will be undefined (like the F (CPOLY) below). The truth is that its parameters are not constant, so don't declare it as const!

*}

Void G (Polygon & Const rPOLY) {

RPOLY.ADDPOINT (Point (1, 1));

}

13. The const there is no effect because it is not possible to change to another object anyway, regardless of a reference. * Void H (POLYGON * const ppoly) {

PPOLY-> AddPoint (Point (2, 2));

}

14. The constings here does not work, but the reasons are different from 13: this is because you use the pointer to the pointer, which is meaningless as the passing const INT parameter told above.

(If you mention the function here in the answer to the additional question, you will generate compilation errors. Will make the function body itself does not conform to C usage.)

* Int main () {

POLYGON POLY;

Const polygon cpol;

f (poly);

It's very good, there is no problem.

* F (cpoly);

Here, when f () attempts to abandon the const attribute to modify its parameters, an uncertain result is generated.

* G (poly);

This statement is no problem.

* H (& poly);

This sentence is no problem.

}

Ok, finally finished! Now getting the correct code version (of course, only the incorrect error ":

Class polygon {

PUBLIC:

POLYGON (): area _ (- 1) {}

Void AddPoint (POINT PT) {invalidatearea ();

Points_.push_back (pt);}

Const Point GetPoint (INT I) const {return points_ [i];

INT getnumpoints () const {return points_.size ();

Double getarea () const {

IF (Area_ <0) // If there is no calculation and saving,

Calcarea (); // then start now.

Return Area_;

}

Private:

Void invalidatearea () const {area_ = -1;}

Void Calcarea () const {

Area_ = 0;

Vector :: Const_ITERATOR i;

For (i = Points_.begin (); i! = points_.nd (); i)

Area_ = / * some work * /;

}

Vector Points_;

Mutable Double Area_;

}

Const Polygon Operator (Const Polygon & LHS,

Const Polygon & RHS) {

POLYGON RET = LHS;

Const int last = rhs.getnumpoints ();

For (int i = 0; i

Ret.Addpoint (rhs.getpoint (i));

Return Ret;

}

Void F (Polygon & Poly) {

POLY.Addpoint (Point (0,0));

}

Void G (POLYGON & RPOLY) {rpoly.addpoint (Point (1, 1));} Void H (Polygon * PPOLY) {PPOLY-> AddPoint (Point (2, 2));

Int main () {

POLYGON POLY;

f (poly);

g (poly);

H (& poly);

}

转载请注明原文地址:https://www.9cbs.com/read-351.html

New Post(0)