Author: Hub Sutter Translator: plpliuly
/ * This article is the sixth article of the Gotw (GURU of the Week) series of self-entertainment translations, the original copyright is the author of Hub Sutter (the famous C expert, "Exceptional C " author). The translation of this article did not have the consent of the original author, only for learning discussion. - Translator * /
# 6 Correct use of Const (proposed on May 21, 1997) Difficulties: 6/10
Use constable as possible, but don't abuse. We will discuss a few more obvious and few things that do not obviously or should not use const places. (Translator: Is it too embarrassing? No way, my translation level It's limited, you are looking at :-))
Question: Const is a tool to write a safer code. And it can also help the compiler to optimize. It should be used as much as possible ... but what is called "as possible"? Do not have the structure of the following procedures and other styles The problem is picking because it is just to make examples. Please simply add or delete "const" in the right place. Additional questions are: What is the procedure Const's error uses to generate compilation errors or udefined results?
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 not yet calculated and cached cagcarea (); // Calculate now return area_;}
Private: void invalidateArea () {area_ = -1;}
Void Calcarea () {area_ = 0; Vector
VECTOR
Polygon Operator (POLYGON & LHS, POLYGON & RHS) {Polygon Ret = LHS; INT Last = rhs.getNumpoints (); for (int i = 0; i Void F (const_cast 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 cpoly; f (poly); f (cpol); g (poly); h (& poly);} answer: Class Polygon {public: polygon (): area _ (- 1) {} Void AddPoint (Const Point Pt); Points_.push_back (Pt);} 1. Since the Point object is passed by the value copy, the declaration is not much more significant. Point getPoint (const INT i) {return points_ [i];} 2. The value of the positive value parameter is usually not used as above, and it will only be misunderstood. 3. This should be a constant member function because it does not change the status of the object. 4. (Controversial) The return value for non-primary types (Non-Builtin) should usually be const. This will help call the function of the function to prevent the returned temporary object (for example, "poly.getpoint (i) = Point (2, 2); "If you really want to do this, getPoint should return to the object's reference, not to return to the temporary object through the piping method. We will see it later, let GetPoint returns const Type or const reference type is very meaningful, because this will be useful in the processing of Const's Polygon object in Operator ()) Note: Lakos opposes returns a const type, he believes that this will prevent instantiation of the template. However, it is worth noting that for the native type, it is indeed necessary to return const types (such as returning "const Int"). [Advice]: For the transmitted value of the non-primary type, try to return a constant type value. Int getnumpoints () {return points_.size ();} 5. This function should also be const. (You should not return here) Const int, because int is already a right value, plus const can impede instantiation of templates, and easy to make people confuse, misunderstanding Double getArea () {if (Area_ <0) // if not yet calculate and cached cagcarea (); // calculate now Return area_;} 6. Although this function changed the internal state of the object, it should be const. because Observable status without changes (we make the AREA_ save the calculation result is just an implementation details, from logical objects should be constant). This means that Area_ should declare to mutable if your compiler is not Support Mutable will be replaced by Const_cast, which will be replaced with the area_ (it is recommended to remove this const_cast) after the compiler supports Mutable, and the function is changed to a const function. Private: void invalidateArea () {area_ = -1;} 7. This It is controversial, but I still recommend setting this function to const, which is just for consistency. (From a semantic, this function will only call in non-const ", because it's the purpose is in object When the state changes make the area value saved by Area_ ineffective) Void Calcarea () {area_ = 0; Vector Polygon Operator (POLYGON & LHS, POLYGON & RHS) {10. Of course, it should be a conveying const reference as a parameter .11. Return type should also be const. Polygon Ret = LHS; int last = rhs.getNumpoints (); 12. Since "Last" does not need to change, then declare the "const Int" type. For (INT i = 0; i Return Ret;} Void f (Const Polygon & Poly) {const_cast } Void g (Polygon & Const rPOLY) {rPOLY.Addpoint (Point (1, 1));} 13. "const" here is useless, because reference is not possible to change to another different object. [Translator Question out: The relationship between the reference and the object referenced is determined when the initialization is initialized, and there will be no changes. Therefore, reference variables must be initialized when declaring, and the class member variable of the reference type must also pass constructor. The initialization sequence is initialized. Void h (POLYGON * const ppoly) {ppoly-> addpoint (Point (2, 2));} 14. This "const" is also redundant, but the reason is different from above: because you pass a pointer value, This way of writing "const Int" is not much different. (If you think the answer to the question is the compiler error, then, I am sorry, this is a very legal C Writing. You may think about it Move "const" to the left of & or *, but will cause compilation errors in the function body [Translator: Move to & or * on the left of the const in the left side of the guide or pointer to the object to be constant, the above code Const meaning is that the guidelines use or pointer itself is constant]) int main () {polygon poly; const polygon cpol; f (poly); f (cpol); if f () attempts to drop the const attribute Cast, then change the parameter value, will generate an uncertain result. g (poly); No problem here. h (& poly); there is no problem here. } Ok, we can finally get a modified version (remember, just modifying const, not all style issues): class polygon {public: polygon (): area _ (- 1) {} void AddPoint (POINT PT) {invalidateArea (); Points_.push_back (pt);} const paget getpoint (INT i) const {return points_ [i];} int getNumpints () const {return points_.size ();} Double getarea () const {if (area_ <0) // if not yet calculated and cached cagcarea (); // Calculate now return area_;} Private: void invalidateArea () const {area_ = -1;} Void Calcarea () const {area_ = 0; Vector Vector Const Polygon Operator (Const Polygon & lhs) {Polygon Ret = LHS; Const Int Last = RHS.GETNUMPOINTS (); for (int i = 0; i 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);} - (end)