clause 20: Prefer to replace pass-by-value with Pass-by-reference-to-const
By default, C + + passes objects to (or from) functions in by value, a way that inherits from C. Unless you specify otherwise, the function arguments are based on the actual argument's complex, and the caller gets a duplicate of the function return value. The creation of a duplicate (copy) takes time and wastes resources, as shown in the following code.
#include <iostream> #include <string> using namespace std;
Class base{Public:base () {cout << "=====base constructor =====" << Endl;
Base (int aa, int bb): A (AA), B (BB) {cout << "=====base constructor =====" << Endl;
virtual void Show () const{cout << a << "" << b << Endl;
Virtual ~base () {cout << "=====base destructor =====" << Endl;
} Private:int A;
int b;
};
Class Derived:p ublic base{public:derived () {cout << "=====derive's constructor =====" << Endl;
Derived (int A, int b): Base (a,b) {cout << "=====derive constructor =====" << Endl;
virtual void Show () const {cout << "subclass Derived" "Show ()" << Endl;
Base::show ();
Virtual ~derived () {cout << "=====derive destructor =====" << Endl;
}
};
void Hello (Base b) {cout << Endl; cout << "=====hello===== "<< Endl;
B.show ();
cout << "---------------" << Endl;
int main () {Base B (1, 2);
Hello (b);
return 0; }
The
results are as follows:
You can find that the base destructor was executed two times, but its constructors were also executed two times, because in the process of passing a value, we can see that copy of the value is not performed once, and therefore the copy process of the value is At the end of the function, destructors are executed automatically, two functions need to be refactored, and two objects need to be refactored, so two destructors appear;
You can see that this behavior requires copying parameters, wasting resources, and reducing the efficiency of program execution. So what can we do to avoid this problem? there is, of course, pass by Reference-to-const: This approach has two advantages: 1) greatly improves the execution efficiency of the program, and no constructors or destructors are invoked. Since no new objects are created, generally we should declare them as const variables, which will guarantee that the reference variables passed in will not be modified; 2 pass-by-reference General pass parameters can also avoid slicing (object cutting) problem. When a derived class object is passed through Pass-by-name as a base class object, the copy constructor of base class is invoked, causing the "object's behavior to the derived class object" All of those features have been cut off, leaving only a base class object, which allows the program developer to dive into deep thinking without knowing where the error is, so we recommend using Pass-by-reference-const for parameter passing, see the following code:
#include <iostream> #include <string> using namespace std;
Class base{Public:base () {} Base (int aa, int bb): A (AA), B (BB) {} virtual void Show () const{
cout << a << "" << b << Endl;
Virtual ~base () {} private:int A;
int b;
}; Class Derived:p ublic base{public:derived () {} Derived (int a, int b): Base (a,b) {} virtual void show
() "Show ()" << Endl in the cout << subclass derived function;
Base::show ();
Virtual ~derived () {}};
void Hello (Base b) {cout << Endl;
cout << "=====hello=====" << Endl;
B.show ();
cout << "---------------" << Endl;
} void Hello2 (const base& b) {cout << Endl;
cout << "=====hello2=====" << Endl;
B.show ();
cout << "---------------" << Endl;
} void Hello3 (base* b) {cout << "=====hello3=====" << Endl;
B->show (); cout << "---------------" << Endl;
int main () {Derived D (1, 2);
Hello (d);
Hello2 (d);
base* B = New Derived (2, 3);
Hello3 (b);
Delete B;
return 0; }
Run Result:
There is a logic pit, the built-in type is generally passed through the pass-by-value, because the pass-by-reference is actually passed through the pointer, for the built-in type, pass-by-value obviously more efficient, while the built-in type of the structure is relatively small, Therefore, some people take it for granted that small types are pass-by-value, even if they are user-defined class also does not matter, this conclusion is wrong. Because there are different classes, at the same time the compiler has different ways of working, therefore, the wise choice is to use pass-by-reference-const delivery, but there are special cases, for built-in types, STL iterators and Function objects, the use of pass-by-value may be more efficient.
Summarize:
1) Try to use Pass-by-reference-to-const to replace Pass-by-value, the former is usually more efficient, and can avoid object cutting problem;
2 The above rules do not apply to built-in types, STL iterators and function objects, for them, pass-by-reference is often more appropriate.
Ps:
1. C + + built-in type
Arithmetic type: character, Integer, bool, floating point;
Empty type: void.
2, C++stl iterator:
Includes input iterator, Output iterator, Forward iterator, bidirectional iterator, Random access iterator these 5 iterators.
3, C + + function objects:
Class a{public
:
A ();
...
int operator () (int x) {return
x;
}
Private:
int x;
};
A A (5);
A (10);
At this point, a (10) is the function object, and similar to this is the function object.