amit kumar
amit kumar

Reputation: 21022

Returning a new object along with another value

I want to return two values, one of which is a new object. I can do this using std::pair:

class A {
//...
};

std::pair<A*, int> getA()
{
   A* a = new A;
   //...
} 

To make the code exception-safe, I would like to do:

std::pair<std::auto_ptr<A>, int> getA()
{
    std::auto_ptr<A> a(new A); 
    //...
} 

But this won't compile as the auto_ptr cannot be copied without modifying the auto_ptr being copied. Ok, this means auto_ptr does not compose well like other types (in one more way). What is a good way of returning a new object in this case?

One alternative is to return a shared_ptr and another is an inout reference. But I am looking for some other alternative. I can do something like:

class AGetter
{
    void getAExecute()
    {
         //...
         // set a_ and i_
    }
    std::auto_ptr<A> getA() const
    {
         return a_.release();
    }
    int getInt() const
    {
         return i_;
    }
    private:
    std::auto_ptr<A> a_;
    int i_;
};

Is there a better way?

Upvotes: 5

Views: 274

Answers (5)

TimW
TimW

Reputation: 8447

Just create a new class and return that class

class Result
{
   A* a;
   int i;
public:
   Result( A*a, int i ) : a(a), i(i) {
   }
   ~Result() { 
      delete a; 
   }
   // access functions, copy constructor, ...
};

Result getA() {
   //...    
   return Result(new A, intValue);  
}

Upvotes: 2

Gab Royer
Gab Royer

Reputation: 9806

A shared_ptr would be ideal in that situation, but if you really don't want to use those you could return an auto_ptr to a pair containing the object and the int instead.

Upvotes: 3

ralphtheninja
ralphtheninja

Reputation: 133008

Why not through two reference parameters?

class AGetter
{
    // ..
    void get(std::auto_ptr<A>& a, int& i)
    {
         a = a_.release();
         i = i_;
    }
    // ..
};

Upvotes: 1

David Seiler
David Seiler

Reputation: 9705

There are two major ways to handle this problem:

  1. Do the cleanup yourself, via try/catch.
  2. Use some kind of automated memory management, like shared_ptr.

auto_ptr doesn't really work in these sorts of cases, as you discovered, but the new standard and Boost both contain reference-counted pointers that do what you want. Let us know what you don't like about shared_ptr, and maybe we can suggest an alternative.

Upvotes: 5

Nathan Kitchen
Nathan Kitchen

Reputation: 4877

It's not pretty, but you could return the other value through a pointer or reference argument:

int i;
std::auto_ptr<A> a = getA(&i);

Upvotes: 1

Related Questions