Class rational {public: Rational (INT Numerator = 0, int Denominator = 1 );... PRIVATE: int N, D; // numerator and denominator friend const rational // See Clause 21: Why operator * (const rational & LHS, // The returned value is const rational & RHs)}; inline const rational operator * (const rational & LHS, const rational & RHs) {return rational (LHS. N * RHS. n, LHS. D * RHS. d );}
Remember that a reference is just a name and the name of another existing object. Whenever you see a referenced statement, you need to immediately ask yourself: what is its other name? Because it must have another name. For operator *, if a function returns a reference, it must return a reference to another existing rational object, which contains the result of multiplying two objects.
However, it is unreasonable to expect such an object to exist before calling operator.
If operator * must return a reference to such a number, it must create the number of objects by itself. A function can create only one new object in two ways: in the stack or on the stack. When an object is created in the stack, it is accompanied by the definition of a local variable. to use this method, we need to write operator * as follows *:
// The first error method for writing this function: inline const rational & operator * (const rational & LHS, const rational & RHs) {rational result (LHS. N * RHS. n, LHS. D * RHS. d); return result ;}
This method should be rejected because our goal is to avoid the constructor being called, but the result must be constructed like other objects. In addition, this function has another more serious problem. It returns a reference to a local object.
Heap-based objects are generated by using new, so you should write operator * as follows *:
// The second error method for writing this function: inline const rational & operator * (const rational & LHS, const rational & RHs) {rational * result = New Rational (LHS. N * RHS. n, LHS. D * RHS. d); return * result ;}
First, you have to pay for the constructor call overhead, because the memory allocated by new is initialized by calling an appropriate Constructor (see article 5 and M8 ). In addition, there is another question: who will delete the newly generated object using delete?
In fact, this is definitely a memory leak. Even if the caller of operator * can persuade the operator * to retrieve the return value address of the function and then delete it with Delete (the operation is very troublesome-Clause 31 shows what such code will look like ), however, some complex expressions generate temporary values without names, which cannot be obtained by programmers. For example:
rational w, x, y, z;w = x * y * z;
Both operator * calls generate temporary values without names, which cannot be viewed by programmers and thus deleted.