As mentioned in more than tive C ++, the real temporary objects in C ++ are invisible and cannot appear in your source code. Creating an unnamed non-heap object will generate a temporary object, which is usually generated under two conditions: when implicit type conversion and function return objects are performed to make the function call successful.
1 size_t countChar(const string& str, char ch);2 3 int main()4 { 5 char c; 6 cin >> c >> setw(MAX_STRING_LEN) >> buffer; 7 cout << "There are " << countChar(buffer, c)<< " occurrences of the character " << c<< " in " << buffer << endl;8 }
View code
In the program, the first input parameter type of countchar is const string &, while the call is to pass in buffer [], a character array, at this time, the compiler will call the string constructor using buffer as the parameter to initialize this temporary object. The countchar parameter STR is bound to this temporary String object. When countchar returns, the temporary object is automatically released. This type conversion is very convenient, but from the perspective of efficiency, the construction and release of temporary string objects are unnecessary overhead. This type conversion occurs only when an object is passed by passing a value or the reference-to-const parameter. When a reference-to-non-const parameter object is passed, this will not happen.
1 void uppercasify (string & Str); 2 3 int main () 4 {5 char subtlebookplug [] = "valid tive C ++"; 6 uppercasify (subtlebookplug); // error! 7}
View code
The line7 program reports an error because the uppercasify function may modify the input parameter while the real parameter is a char array. Therefore, a temporary object is created when the function is called, and the temporary object has the const attribute, the input parameter of the function is a reference of non-const and cannot be assigned a value. Therefore, the C ++ Language prohibits the generation of temporary objects for reference-to-non-Const.
The second environment for creating a temporary object is when the function returns an object: const number operator + (const number & LHS, const number & RHs ); it is difficult for a function to return an object to have a high efficiency, because passing a value to return results in calling the constructor and destructor in the object, which cannot be avoided. Returning an object in some way can eliminate the overhead of the temporary object by the compiler. Therefore, it is common to compile functions. This technique is to return the constructor argument instead of directly returning the object.
1 const Rational operator*(const Rational& lhs, const Rational& rhs) 2 { 3 return Rational(lhs.numerator() * rhs.numerator(), lhs.denominator() * rhs.denominator()); 4 }
View code
The constructor argument is returned without local objects. The C ++ rule allows the compiler to optimize temporary objects (temporary objects out of existence) that are not present ).
1 int main()2 {3 Rational a = 10; 4 Rational b(1, 2); 5 Rational c = a * b;6 7 return 0;8 }
View code
Program line6, the compiler will be allowed to eliminate the temporary variables in operator * and the temporary variables returned by operator. They can construct the objects defined by the return expression in the memory allocated for the target c. If your compiler does this, the overhead of the temporary object that calls operator * is zero: no temporary object is created. Your cost is to call a constructor-the constructor called when C is created. In addition, you cannot do better than this because C is a named object and the named object cannot be eliminated.
When a function returns an object, creating and destroying a temporary object is unnecessary. Therefore, nrv technology can be used to reduce unnecessary overhead and improve program efficiency. Named return value optimization: the optimization of the specified return value is an optimization operation of the compiler. It is regarded as an unshirkable optimization operation for the Standard C ++, reference the example in Deep Exploration C ++ object model:
1 X Bar () 2 {3 x xx; 4 //... handle XX 5 return xx; 6} 7 // The Compiler replaces xx with _ result: 8 void bar (X & __ result) 9 {10 // default constructor calls 11 // C ++ pseudocode 12 _ result. x: X (); 13 14 //... directly process _ result15 16 return; 17}
View code
Here, the compiler replaces named return value with the result parameter, and does not call copy constructor to copy the result. A more detailed description is as follows:
A A = f ();
Here, the F () function creates Class A object B, and then returns object B. When object B returns, it generally calls the copy constructor to put the function f () partial object B inside is copied to object a outside the function. However, if nrv optimization is used, you do not have to call the copy constructor. the compiler can do this: pass the address of A to F (), so that F () will not create the returned object B and use a to replace the address of B. In this way, when the object B is returned, no copy is required, because B is.
The copy construct function must be provided to activate nrv in Deep Exploration C ++ object model. The test in vs2010 is as follows:
1 using namespace std; 2 class Complex 3 { 4 friend Complex operator+(const Complex&, const Complex&); 5 public: 6 Complex(double r=0.0, double i=0.0):real(r),imag(i) 7 { 8 cout<<"Complex real="<<r<<", imag="<<i<<endl; 9 }10 Complex(const Complex& c):real(c.real), imag(c.imag)11 {12 cout<<"Complex(const Complex& c), real="<<real<<", imag="<<imag<<endl;13 }14 Complex& operator=(const Complex& c)15 {16 cout<<"Complex& operator=, real="<<c.real<<", imag="<<c.imag<<endl;17 if(this == &c)18 return *this;19 real = c.real;20 imag = c.imag;21 }22 ~Complex()23 {24 cout<<"~Complex(), real="<<real<<", imag="<<imag<<endl;25 }26 private:27 double real;28 double imag;29 };30 Complex operator+(const Complex& a, const Complex& b)31 {32 // Complex retVal(a.real + b.real, a.imag + b.imag);33 // return retVal;34 return Complex (a.real + b.real, a.imag + b.imag);35 }36 37 int _tmain(int argc, _TCHAR* argv[])38 {39 Complex a(12, 23), b(23, 34);40 Complex c = a+b;41 42 cout<<"################################"<<endl;43 44 return 0;45 }
View code
The above Code has the same results under the debug/release option:
?
If you modify the complex operator + function:
1 Complex operator+(const Complex& a, const Complex& b)2 {3 Complex retVal(a.real + b.real, a.imag + b.imag);4 return retVal;5 }
View code
The output results under the debug/release option are different:
Debug:
Release:
Temporary object and nrv Technology