anatolyg
anatolyg

Reputation: 28241

Ignoring a return-by-reference result from a function

Suppose i have a function that returns an important result and several unimportant results. I declared it so that the unimportant results are returned by reference:

int CalculateStuff(int param1, int param2, int& result1, int& result2);

I would like to call this function to calculate some stuff, but at call site i want to ignore the unimportant results. I could do it as follows:

...
int dummy1, dummy2;
int result = CalculateStuff(100, 42, dummy1, dummy2);
... // do something with the result

I would like to consider another way to do the same without declaring dummy variables:

int result = CalculateStuff(100, 42, *new int, *new int);

This has a memory leak (unacceptable), but has an advantage of showing my intent (ignoring the results) more clearly than the "dummy" names.

So, what would happen if i wrote it as follows:

int result = CalculateStuff(100, 42, auto_ptr(new int).get(), auto_ptr(new int).get());

Is it legal? Will the temporary integers still exist when the function's code is executed? Should i use unique_ptr instead of auto_ptr?

(Please don't suggest refactoring my code; i probably will - but first i want to understand how this stuff works)

Upvotes: 6

Views: 1600

Answers (6)

James Kanze
James Kanze

Reputation: 153909

It's legal, but it's not guaranteed not to leak memory, see question 3 here for example.

The correct and idiomatic way of implementing optional output is to pass a pointer, passing NULL when you don't want the results, and testing for NULL in the function before writing through the pointer.

Upvotes: 2

visitor
visitor

Reputation: 1801

You could make a class that provides implicit (or explicit) conversion to int&.

struct ignored
{
   int n;
   operator int&() { return n; }
};

n = CalculateStuff(a, b, ignored(), ignored());

You can further make this a template and add const overloads.

Upvotes: 3

hamstergene
hamstergene

Reputation: 24429

It is legal; auto_ptr objects will remain alive until the end of expression (i.e. function call). But it is ugly as hell.

Just overload your function:

int CalculateStuff(int param1, int param2, int& result1, int& result2);
int CalculateStuff(int param1, int param2) { 
    int r1=0, r2=0; 
    return CalculateStuff(param1, param2, r1, r2);
}

Upvotes: 4

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361352

According to Bjarne Stroustrup, if some parameters are optional, it is an ideal case for making them pointer type, so that you can pass NULL when you don't need to pass arguments for them:

int CalculateStuff(int param1, int param2, int * result1, int * result2);

And use:

int result = CalculateStuff(100, 42, NULL, NULL);

All other alternatives would not be as good as this one, or at least not better than this.

Of course, the implementation of CalculateStuff has to check the parameters if they're NULL or not.

Upvotes: 4

pmr
pmr

Reputation: 59811

A recommended approach if you have control over the function would be: return a std::tuple (or boost::tuple) with all results or write an overload that doesn't need the extra variables.

Upvotes: 3

NPE
NPE

Reputation: 500287

Here is my advice: if you have to ask on SO to figure out the correctness of the code and its semantics, then the code fails at clearly expressing your intent.

I think the first version (with dummy1 and dummy2) is the most transparent, and is obviously correct.

If you find yourself repeatedly calling the function and not wanting the optional results, you could provide an overload:

int CalculateStuff(int param1, int param2, int& result1, int& result2) {}

int CalculateStuff(int param1, int param2) {
  int unwanted1, unwanted2;
  return CalculateStuff(param1, param2, unwanted1, unwanted2);
}

Upvotes: 3

Related Questions