2010-10-17 2 views
4

Я смущен между:Каков правильный способ возврата объекта из C++?

  • возвращающим объектом (но тогда объект копируется из локальных переменных в функции, которая потребляет память)
  • возвращающие указателя (но тогда у вас есть помните, чтобы удалить его, в вызывающем коде, который является странным)
  • , возвращающий ссылку (но это невозможно, поскольку это будет ссылка на локальную переменную функции, которая будет удалена, как только функция заканчивается)

Я ищу подходящий способ возврата объекта из C++-функции в базовый C++ (без указателей обработки библиотеки и автоматического освобождения памяти). Я хочу знать, как это должно быть сделано.

Спасибо

+0

Duplicate: http://stackoverflow.com/questions/3350385/how-to-return-an-object-in-c – GManNickG

+0

Извините за дубликат, поиск не выявил это, когда я попытался –

+1

Это хорошо , Поиск на SO ... отсутствует. – GManNickG

ответ

8

Современные компиляторы обычно реализуют (Named) Return Value Optimization, с помощью которого копия, которую вы ссылаетесь (и логически ожидаете), не выполняется.

С тех пор, как Visual Studio 2005 (VC++ 8.0) Я не думаю дважды о возвращении объектов.

+1

ой! gcc тоже? Кажется, что это «трюк» ... C++ просто кажется неправильным :( –

+1

+1: Доверяйте своему компилятору, RVO/NRVO очень эффективны в своей работе. – Puppy

+0

gcc и intel тоже, да. Каждый компилятор стоит своей соли. – Blindy

3

насчет std::auto_ptr от <memory>? Или, если речь идет о C++ 0x std::unique_ptr?

+0

Я думаю, он спрашивает о более фундаментальных шаблонах. –

+0

@quixoto: Ну дайте им :) –

+0

У меня нет отличного ответа здесь, сам смотрел на вопрос. –

0

Возврат по стоимости, если вам не нужен полиморфизм подтипа. В последнем случае я бы вернул auto_ptr<T> (C++ 03) или unique_ptr<T> (C++ 0x).

1

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

Следует использовать ссылки, если это возможно. Но если вы должны вернуть указатель, использование класса интеллектуального указателя, такого как std :: auto_ptr или boost :: shared_ptr, является хорошей идеей, потому что тогда вызывающему коду не нужно задумываться о том, чтобы освободить его, когда он с ним сделан.

0
  • Возвращение один из умных выбора указателей (либо необходимости в зависимости от дополнительных библиотек, или подождать до тех пор, C++ 1x)
  • Используйте проход по ссылке

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

+0

Является ли C++ 0x? Я знаю, что некоторые компиляторы поддерживают его части сейчас, но это не завершено, не так ли? – 2010-10-17 14:57:05

+0

@PhilCK: Нет, мы все НАДЕЕМСЯ, что он будет завершен в следующем году. Хотя некоторые считают, что 2012 год более реалистичен. –

+0

Следовательно, 1x. Некоторые говорят, что в конечном итоге это будет 2x -_- я, конечно, надеюсь, что нет. –

2

Предполагая, что «обращению нет библиотеки указателей и автоматически освобождая память» не означает, что нет возврата-на-указатель, не boost::shared_ptr и не std::unique_ptr (std::auto_ptr это evil в любом случае), у вас есть два варианта:

Возврат по значению:

Foo bar(quux) 
{ 
    Foo foo; 
    foo.frobnicate(quux); 
    return foo; 
} 

Foo foo = bar("fred"); 

Pass по ссылке:

void bar(Foo& foo, quux) 
{ 
    foo.frobnicate(quux); 
} 

Foo foo; 
bar(foo, "fred"); 
+0

+1 для шаблона «явный объект в вызывающем, ссылочном аутореме». – zwol

3

несколько правил т Хумбы относительно возвращающихся объектов из функций:

Возвращаемых за копию, кроме случаев, когда

  1. вы возвращаетесь нелокального объект (как член класса, статические переменные и т.д.) тип, который вы бы pass to a function per const reference; вы можете вернуть этот за const ссылка
  2. вы возвращаетесь нелокальной объект и абоненты должны иметь возможность Invoke модификации членов возвращаемого объекта, тем самым манипулируя объект, хранящийся в другом месте; вернуть этот за не- const ссылка
  3. вы возвращаетесь производный класс в иерархии полиморфных классов, пользователи объекта должны знать только базовый класс, и ни # 1, ни # 2 применяется; вернуть этот за смарт-указатель
0

возвращающего объект (но тогда объекта копируется из локального переменных в функции, которая потребляет память)

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

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

Да, вы должны помнить, чтобы удалить его, как вы этого не сделаете хочу рассмотреть автоматическую очистку для этого вопроса.

возвращает ссылку (но это не возможно потому, что это будет ссылки на локальный переменные функциях , которые будут удалены только функция заканчивается)

Возвращаемая ссылка полезна, когда вы возвращаете этот объект (* this) из функций-членов. В противном случае, как вы упомянули, его невозможно использовать.

В целом: это зависит от вашей потребности, как описано выше относительно того, какой из них выбрать.

Смежные вопросы