.. _structures-pass-by-reference: Pass by reference ----------------- .. index:: single: pass by reference An alternative parameter-passing mechanism that is available in C++ is called "pass by reference." This mechanism makes it possible to pass a structure to a procedure and modify it. For example, you can reflect a point around the 45-degree line by swapping the two coordinates. The most obvious (but incorrect) way to write a ``reflect`` function is something like this: :: void reflect (point p) { // WRONG !! double temp = p.x; p.x = p.y; p.y = temp; } But this won’t work, because the changes we make in ``reflect`` will have no effect on the caller. Instead, we have to specify that we want to pass the parameter by reference. We do that by adding an ampersand (``&``) to the parameter declaration: :: void reflect (point& p) { double temp = p.x; p.x = p.y; p.y = temp; } Now we can call the function in the usual way: :: print_point (blank); reflect (blank); print_point (blank); Take a look at the active code below. ``reflect`` passes the parameter ``p`` by reference. Notice that the output of this code matches what we expect it to be. .. tb-code:: cpp :name: call_by_reference_AC_1 :caption: Example call_by_reference_AC_1 #include struct point { double x; double y; }; void reflect (point& p) { double temp = p.x; p.x = p.y; p.y = temp; } void print_point (point p) { std::cout << '(' << p.x << ", " << p.y << ")\n"; } int main() { point blank = { 3.0, 4.0 }; print_point (blank); reflect (blank); print_point (blank); } :: (3, 4) (4, 3) Here's how we would draw a stack diagram for this program: .. digraph:: state :name: fig_pass_by_reference_stack :caption: Function call stack diagram :alt: function call stack diagram :align: center graph [compound = true]; fontname = "Bitstream Vera Sans" node [ shape=record fontname = "Bitstream Vera Sans" fontsize = 11 style=filled fillcolor=lightblue ] subgraph cluster_main { labelloc=top; subgraph cluster_0 { label="blank" main [label="x: 3 | y: 4"] } } subgraph cluster_func { label="print_point" labelloc=top; subgraph cluster_1 { label="p" reflect [shape="point"] } } main -> reflect [style=invis]; reflect:e -> main:e; The parameter ``p`` is a reference to the structure named ``blank``. The usual representation for a reference is a dot with an arrow that points to whatever the reference refers to. The important thing to see in :numref:`fig_pass_by_reference_stack` is that any changes that ``reflect`` makes in ``p`` will also affect ``blank``. Passing structures by reference is more versatile than passing by value, because the callee can modify the structure. It is also faster, because the system does not have to copy the whole structure. On the other hand, it is less safe, since it is harder to keep track of what gets modified where. Nevertheless, in C++ programs, almost all structures are passed by reference almost all the time. In this book I will follow that convention. .. tb-group:: :name: self_check .. tb-tab:: Q1 .. tb-blank:: :name: call_by_reference_1 Which symbol should you put in front of the data type of the parameter of a function to make it pass by reference? {{blank}} .. tb-answer:: :match: & :feedback: Correct! :incorrect: Try again! .. tb-tab:: Q2 .. tb-choice:: :name: call_by_reference_2 Which is NOT a benefit to using pass by reference instead of pass by value? - [ ] Passing structures by reference is more versatile - Try again! Passing by reference is more versatile. - [ ] Passing structures by reference is faster, because the system does not have to copy the whole structure - Try again! Passing by reference does not involve making copies. - [ ] In C++ programs, almost all structures are passed by reference almost all the time - Try again! - [x] Passing structures by reference is less safe, since it is harder to keep track of what gets modified where + Correct! .. tb-tab:: Q3 .. tb-choice:: :name: call_by_reference_3 What will print? .. code-block:: cpp int add_two(int& x) { cout << x << ' '; x = x + 2; cout << x << ' '; return x; } int main() { int num = 2; add_two(num); cout << num << '\n'; } - [ ] ``2 4`` - Take a look at exactly what is being outputted. - [ ] ``2 4 2`` - Remember the rules of pass by reference. - [ ] ``4 4 2`` - Take a look at exactly what is being outputted. - [x] ``2 4 4`` + Correct! .. tb-tab:: Q4 .. tb-choice:: :name: call_by_reference_4 What will print? .. code-block:: cpp struct point { int x, y; }; void times_two (point& p) { p.x = p.x * 2; p.y = p.y * 2; cout << '(' << p.x << ", " << p.y << ')'; } int main() { point blank = { 3, 4 }; times_two (blank); cout << ", " << blank.x << '\n'; } - [ ] ``(6, 8), 3`` - The ``&`` indicates pass by reference. - [x] ``(6, 8), 6`` + Correct! - [ ] ``(6.0, 8.0) 3.0`` - The ``&`` indicates pass by reference. Take a look at the data type. - [ ] ``686`` - Take a look at exactly what is being printed.