Разница между типами функций - PullRequest
2 голосов
/ 26 марта 2012

В чем разница между ними?

MyType myFunction();

MyType t = myFunction();

И

MyType &myFunction();

MyType t = myFunction();

И

const MyType &myFunction();

MyType t = myFunction();

Что происходит за кулисами?

Ответы [ 4 ]

3 голосов
/ 26 марта 2012

В трех случаях вторая строка является общей:

MyType t = myFunction();

Эта строка получает результат вызова myFunction и использует его для copy-construct нового элемента MyType с именем t.

Теперь о различиях. В первом случае вы возвращаете по значению, что означает (семантически), что компилятор создаст копию объекта, содержащегося в операторе return внутри myFunction, а затем использует эту копию в качестве источника для построения копии. t. Компилятор, скорее всего, исключит копии (по крайней мере, второй).

В двух других случаях функции возвращают ссылки на какой-либо другой объект. Если объекты являются локальными, то это неопределенное поведение. Разница между ними заключается в том, может ли возвращенная ссылка использоваться для изменения упомянутого объекта или нет, и это может повлиять на то, какой конструктор копирования используется, или его можно использовать вообще. Помните, что объект, с которого вы получаете ссылку, должен пережить вызов функции, иначе вы будете вызывать неопределенное поведение.

// an example where it matters:
typedef std::auto_ptr<int> MyType;
MyType t = myFunction();

Поскольку std::auto_ptr изменяет правую часть при назначении, предыдущий код будет работать только в том случае, если возвращаемая ссылка неконстантна.

Лучиан указывает, что возвращение ссылки , скорее всего, будет неопределенным поведением , так когда бы это было не так? Когда объект, из которого была получена ссылка, переживает использование ссылки. Это основной строительный блок синглтона Meyers:

// an example where returning a reference is correct
MyType & myFunction() {
  static MyType instance;   // Note static storage duration!
  return instance;
}

Или любой простой метод доступа, который возвращает ссылку на подобъект. Некоторые из распространенных случаев - operator[] в контейнерах (обычно они не копируют значение, а возвращают ссылку на сохраненные данные).

Но это правда, что чаще всего функции возвращают статически не живые объекты, а локальные.

1 голос
/ 26 марта 2012

Я предполагаю, что это бесплатные функции.

MyType myFunction();
MyType t = myFunction();

возвращает объект MyType по значению.Теоретически, объект, созданный внутри myFunction, копируется при возврате.Практически, RVO, скорее всего, произойдет.

MyType &myFunction();
MyType t = myFunction();

возвращается по ссылке.Скорее всего, это будет неопределенное поведение , поскольку возвращать локальные объекты по ссылке запрещено.Однако, если myFunctions является функцией-членом, вы можете вернуть MyType, который является членом класса, и все будет в порядке, пока экземпляр переживает t.

Для второгофрагмент кода, вы должны получить предупреждение - «возвращение локальной переменной по ссылке» или что-то подобное.

0 голосов
/ 26 марта 2012

Большинство ответов дают правильные значения, за исключением одной маленькой детали.

const MyType& t = myFunction();

Может показаться, что если myFunction () возвращает временную переменную, это будет неопределенным поведением, но в действительности это не так.Это не UB, и фактически ссылка на const продлевает время жизни временного элемента до времени жизни ссылки на const.Фактически, это единственная версия с наибольшим потенциалом для оптимизации компилятора, а также важный урок: всегда, когда это возможно, всегда возвращать возвращаемые значения в константную ссылку.

0 голосов
/ 26 марта 2012

Я думаю, что вы хотите сделать что-то вроде:

MyType *myFuntion()
{
  MyType *t = new MyType;
  // do something with t
  return t;
}

// ... somewhere else ...
MyType *t = myFunction();

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

 delete t;

где-то позже!

...