Возврат нового объекта вместе с другим значением - PullRequest
5 голосов
/ 22 июня 2009

Я хочу вернуть два значения, одно из которых является новым объектом. Я могу сделать это, используя std::pair:

class A {
//...
};

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

Чтобы сделать код безопасным от исключений, я хотел бы сделать:

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

Но это не скомпилируется, поскольку auto_ptr нельзя скопировать без изменения копируемого auto_ptr. Хорошо, это означает, что auto_ptr не так хорошо сочетаются, как другие типы (еще одним способом). Каков хороший способ возврата нового объекта в этом случае?

Одна из альтернатив - вернуть shared_ptr, а другая - это ссылка на вход. Но я ищу другую альтернативу. Я могу сделать что-то вроде:

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_;
};

Есть ли лучший способ?

Ответы [ 5 ]

5 голосов
/ 22 июня 2009

Существует два основных способа решения этой проблемы:

  1. Выполните очистку самостоятельно, с помощью try / catch.
  2. Используйте какое-то автоматическое управление памятью, например shared_ptr.

auto_ptr действительно не работает в подобных случаях, как вы обнаружили, но новый стандарт и Boost содержат указатели с подсчетом ссылок, которые делают то, что вы хотите. Дайте нам знать, что вам не нравится в shared_ptr, и, возможно, мы можем предложить альтернативу.

3 голосов
/ 22 июня 2009

A shared_ptr было бы идеально в такой ситуации, но если вы действительно не хотите использовать их, вы можете вернуть auto_ptr паре, содержащей объект и int вместо этого.

2 голосов
/ 22 июня 2009

Просто создайте новый класс и верните этот класс

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);  
}
1 голос
/ 22 июня 2009

Почему не через два эталонных параметра?

class AGetter
{
    // ..
    void get(std::auto_ptr<A>& a, int& i)
    {
         a = a_.release();
         i = i_;
    }
    // ..
};
1 голос
/ 22 июня 2009

Это не красиво, но вы можете вернуть другое значение через указатель или ссылочный аргумент:

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