Возврат объектов в C++

С join() и zip().

>>> ''.join(''.join(item) for item in zip(u,l))
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
34
задан Eclipse 6 January 2009 в 21:29
поделиться

9 ответов

В зависимости от Вашего использования существует несколько опций, с которыми Вы могли пойти сюда:

  1. Делают копию каждым разом, когда Вы создаете животное:

    class AnimalLister 
    {
    public:
      Animal getNewAnimal() 
      {
        return Animal();
      }
    };
    
    int main() {
      AnimalLister al;
      Animal a1 = al.getNewAnimal();
      Animal a2 = al.getNewAnimal();
    }
    

    Профессионалы:

    • Легкий понять.
    • Не Требует никаких дополнительных библиотек или поддерживающий код.

    Недостатки:

    • Это требует Animal иметь конструктора копии хорошего поведения.
    • Это может включить большое копирование, если Animal larg и комплекс, хотя оптимизация возвращаемого значения может облегчить это во многих ситуациях.
    • не работает, если Вы планируете возврат подклассов, полученных от Animal, как они будут , резал вниз к плоскости Animal, теряя все дополнительные данные в подклассе.
  2. Возврат shared_ptr<Animal>:

    class AnimalLister 
    {
    public:
      shared_ptr<Animal> getNewAnimal() 
      {
        return new Animal();
      }
    };
    
    int main() {
      AnimalLister al;
      shared_ptr<Animal> a1 = al.getNewAnimal();
      shared_ptr<Animal> a2 = al.getNewAnimal();
    }
    

    Профессионалы:

    • Работы с иерархиями объектов (никакое разрезание объекта).
    • Никакие проблемы с необходимостью скопировать большие объекты.
    • Никакая потребность в Animal для определения конструктора копии.

    Недостатки:

    • библиотеки Requires или Boost или TR1 или другая реализация интеллектуального указателя.
  3. Дорожка весь Animal выделения в [1 110]

    class AnimalLister 
    {
      vector<Animal *> Animals;
    
    public:
      Animal *getNewAnimal() 
      {
        Animals.push_back(NULL);
        Animals.back() = new Animal();
        return Animals.back();
      }
    
      ~AnimalLister()
      {
         for(vector<Animal *>::iterator iAnimal = Animals.begin(); iAnimal != Animals.end(); ++iAnimal)
            delete *iAnimal;
      }
    };
    
    int main() {
      AnimalLister al;
      Animal *a1 = al.getNewAnimal();
      Animal *a2 = al.getNewAnimal();
    } // All the animals get deleted when al goes out of scope.
    

    Профессионалы:

    • Идеал для ситуаций, где Вы нуждаетесь в наборе [1 111] с для ограниченного количества времени и планируете выпустить их внезапно.
    • Легко адаптируемый к пользовательским пулам памяти и выпускающий весь Animal с на сингле delete.
    • Работы с иерархиями объектов (никакое разрезание объекта).
    • Никакие проблемы с необходимостью скопировать большие объекты.
    • Никакая потребность в [1 114] для определения конструктора копии.
    • Никакая потребность во внешних библиотеках.

    Недостатки:

    • реализация, как записано выше не ориентирована на многопотоковое исполнение
    • , Требует дополнительного кода поддержки
    • менее ясный, чем предыдущие две схемы
    • , неочевидно, что, когда AnimalLister выходит из объема, это собирается взять Животных с ним. Вы не можете держаться за Животных больше, чем Вы зависаете на AnimalLister.
36
ответ дан Eclipse 10 October 2019 в 13:45
поделиться

Я советую возвращаться std::tr1::shared_ptr (или boost::shared_ptr, если Ваша реализация C++ не имеет TR1) вместо необработанного указателя. Так, вместо того, чтобы использовать Animal*, используйте std::tr1::shared_ptr<Animal> вместо этого.

Общие указатели обрабатывают ссылочное отслеживание для Вас и удаляют объект автоматически, при отсутствии ссылок, оставленных ему.

24
ответ дан Chris Jester-Young 10 October 2019 в 13:45
поделиться

simpliest путь состоит в том, чтобы возвратить интеллектуальный указатель вместо регулярных указателей. Например:

std::auto_ptr< Animal> getNewAnimal() 
{
  std::auto_ptr< Animal > animal1( new Animal() );
  return animal1;
}

, Если Вы в состоянии использовать TR1 или Повышение, можно также использовать shared_ptr<>.

8
ответ дан Igor Semenov 10 October 2019 в 13:45
поделиться

Своего рода классическая проблема с указателями и выделенной памятью. Это об ответственности - кто ответственен за чистку памяти, выделенной объектом AnimalLister.

Вы могли сохранить от указателя на каждое из тех выделенных Животных в самом AnimalLister и иметь его, очищают вещи.

, Но, у Вас действительно есть несколько указателей на Животных, сидящих там в основном (), который сослался бы на память, которая была удалена.

Одна из причин я думаю, что решения для подсчета ссылок работают лучше, чем прокрутка Вашего собственного решения.

8
ответ дан itsmatt 10 October 2019 в 13:45
поделиться
  1. shared_ptr (который работает хорошо),
  2. возвращают простой указатель и говорят пользователю Вашего класса, что это - их животное теперь, и они несут ответственность удалить его по окончании,
  3. реализуют 'freeAnimal (Животное*)' метод, который делает его очевидным, что удаление указателя животных требуется.

  4. альтернативный путь состоит в том, чтобы просто возвратить объект животных непосредственно, никакие указатели, никакие вызовы к новому. Конструктор копии удостоверится, что вызывающая сторона добирается, их собственное животное возражают, что они могут сохранить на "куче" или стеке, или копировать в контейнер, как они требуют.

Так:

class AnimalLister 
{
Animal getAnimal() { Animal a; return a; }; // uses fast Return Value Optimisation
};

Animal myownanimal = AnimalLister.getAnimal(); // copy ctors into your Animal object

RVO означает, что возврат объекта вместо указателя на самом деле быстрее (поскольку компилятор не создает новый объект и копирует его в объект вызывающей стороны, но использует объект вызывающей стороны непосредственно).

5
ответ дан gbjbaanb 10 October 2019 в 13:45
поделиться

Или Вы могли следовать за подходом COM-выхода и применить простой подсчет ссылок.

  • при создании объекта дайте ему ссылочное значение 1 немедленно
  • , Когда любой получает копию указателя, они AddRef ()
  • , Когда любой бросает их копию указателя, они Выпуск ()

, Если подсчет ссылок совершает нападки 0, объект удаляет себя.

в конечном счете, что shared_ptr делает под капотом, но это дает Вам больше контроля тем, что продолжается, и по моему опыту легче отладить. (Его также очень межплатформенный).

я не дал shared_ ptr слишком много шанса в моей разработке пока еще, так, чтобы мог служить Вашим целям отлично.

2
ответ дан brianb 10 October 2019 в 13:45
поделиться

Время для освобождения памяти, занятой объектом, - когда Вам больше не нужен тот конкретный объект. В Вашем особом случае пользователе класса AnimalLister запросил указатель на новый выделенный объект класса Животное. Так, он - тот, который ответственен за освобождение памяти, когда ему действительно больше нужен тот указатель/объект.

AnimalLister lister;
Animal* a = lister.getNewAnimal();
a->sayMeow();
delete a;

, По-моему, нет никакой потребности сверхспроектировать что-либо в этом случае. AnimalLister является просто фабрикой, которая создает новые объекты Животных и вот именно.

2
ответ дан martinsb 10 October 2019 в 13:45
поделиться

Мне действительно нравится ответ Josh's, но я думал, что мог бы добавить другой шаблон, потому что он еще не был перечислен. Идея является просто силой клиентский код для контакта с отслеживанием животных.

class Animal
{
...
private:
  //only let the lister create or delete animals.
  Animal() { ... }
  ~Animal() { ... } 
friend class AnimalLister;
...
}

class AnimalLister 
{
  static s_count = 0;

public:
  ~AnimalLister() { ASSERT(s_count == 0); } //warn if all animals didn't get cleaned up

  Animal* NewAnimal() 
  {
    ++count;
    return new Animal();
  }

  void FreeAnimal(Animal* a)
  {
    delete a;
    --s_count;
  }
}
0
ответ дан BigSandwich 10 October 2019 в 13:45
поделиться

В подробном обсуждении Скоттом Мейерсом он приходит к выводу, что лучше всего использовать shared_ptr или auto_ptr.

3
ответ дан 27 November 2019 в 16:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: