Patrick Dezecache February 2016

Pass a parameter by const reference to a non-void function : is it considered as a side effect?

What is the cleanest way to write a function (not a procedure) ?

Does the 2nd solution is told to have "side effect" ?

struct myArea
{
  int t[10][10]; // it could by 100x100...
};

Solution 1 : pass by value

 double mySum1(myArea a)
 {
   // compute and return the sum of elements
 }

Solution 2 : pass by const reference

double mySum2(const myArea & a)
{
  // compute and return the sum of elements
}

My prefered is the first one (clean function) although it is less effective. But when there are a lot of data to copy, it can be time-consuming.

Thank you for feedback.

Answers


Armen Tsirunyan February 2016

Please note there is no such thing as "procedure" in C++. Functions that don't return anything are still functions.

Now to the question: If your parameter is an output parameter or an input/output parameter, that is, you want the caller to see changes made inside the function to the object passed to it, then pass by reference. Otherwise if the type is small/trivially cheap to copy, pass by value. Otherwise, pass by reference to const. In your case I'd pass by reference to const.


molbdnilo February 2016

Parameter-passing is not a side effect in itself.

If a function does anything observable that isn't just returning a value, that would be a side effect.
(For example modifying a reference parameter, printing something, modifying any global state...)

That is, even if you pass by non-const reference, the presence of side effects depends on whether you modify the referenced object.


paulsm4 February 2016

I have a number of quibbles with your terminology:

  1. There's no such thing as a "procedure" in C or C++. At best, there are functions that return no value: "void"

  2. Your example has no "side effect".

  3. I'm not sure what you mean by "clean function" ... but I HOPE you don't mean "less source == cleaner code". Nothing could be further from the truth :(

TO ANSWER YOUR ORIGINAL QUESTION:

  1. In your example, double mySum1(myArea a) incurs the space and CPU overhead of a COMPLETELY UNNECESSARY COPY. Don't do it :)

  2. To my mind, double mySum1(myArea & a) or double mySum1(myArea * a) are equivalent. Personally, I'd prefer double mySum1(myArea * a) ... but most C++ developers would (rightly!) prefer double mySum1(myArea & a).

  3. double mySum1 (const myArea & a) is best of all: it has the runtime efficiency of 2), and it signals your intent that it WON'T modify the array.

PS: I generated assembly output from the following test:

struct myArea {
  int t[10][10];
};

double mySum1(myArea a) {
  double sum = 0.0;
  for (int i=0; i < 10; i++)
    for (int j=0; j<10; j++)
      sum += a.t[i][j];
  return sum;
}

double mySum2(myArea & a) {
  double sum = 0.0;
  for (int i=0; i < 10; i++)
    for (int j=0; j<10; j++)
      sum += a.t[i][j];
  return sum;
}

double mySum3(myArea * a) {
  double sum = 0.0;
  for (int i=0; i < 10; i++)
    for (int j=0; j<10; j++)
      sum += a->t[i][j];
  return sum;
}

double mySum4(const myArea & a) {
  double sum = 0.0;
  for (int i=0; i < 10; i++)
    for (int j=0; j<10; j++)
      sum += a.t[i] 

Post Status

Asked in February 2016
Viewed 2,913 times
Voted 6
Answered 3 times

Search




Leave an answer