Как правильно вернуть объект из функции C ++? - PullRequest
4 голосов
/ 17 октября 2010

Я запутался между:

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

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

Спасибо

Ответы [ 8 ]

8 голосов
/ 17 октября 2010

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

Начиная с Visual Studio 2005 (VC ++ 8.0), я не думаю дважды о возврате объектов.

3 голосов
/ 17 октября 2010

Несколько правил о возвращении объектов из функций:

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

  1. вы возвращаете нелокальный объект (например, член класса, статическая переменная и т. Д.) Типа, который вы бы передавали в функцию по const ссылке ;вы можете вернуть за const ссылку
  2. вы вернете нелокальный объект , и вызывающие абоненты должны бытьспособен вызывать модифицирующие элементы возвращаемого объекта, тем самым манипулируя объектом, хранящимся в другом месте;вернуть для не- const ссылки
  3. вы вернете производный класс в полиморфную иерархию классов ,пользователи объекта должны знать только базовый класс, и ни # 1, ни # 2 не применяются;верните это за умный указатель
3 голосов
/ 17 октября 2010

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

2 голосов
/ 17 октября 2010

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

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

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

Foo foo = bar("fred");

Передача по ссылке:

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

Foo foo;
bar(foo, "fred");
1 голос
/ 17 октября 2010

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

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

0 голосов
/ 17 октября 2010

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

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

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

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

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

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

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

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

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

0 голосов
/ 17 октября 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...