Подтвердить что ты не робот

С++: возвращает значение L-значение?

Рассмотрим этот код:

struct foo
{
  int a;
};

foo q() { foo f; f.a =4; return f;}

int main()
{
  foo i;
  i.a = 5;
  q() = i;
}

Никакой компилятор не жалуется на это, даже Clang. Почему строка q() = ... верна?

4b9b3361

Ответ 1

Нет, возвращаемое значение функции является l-значением тогда и только тогда, когда оно является ссылкой (С++ 03). (5.2.2 [expr.call]/10)

Если возвращаемый тип был базовым, тогда это будет ошибкой компиляции. (5.17 [expr.ass]/1)

Причиной этого является то, что вам разрешено вызывать функции-члены (даже не- const функции-члены) по r-значениям типа класса, а назначение foo - это определенная функция-член реализации: foo& foo::operator=(const foo&). Ограничения для операторов в разделе 5 применяются только к встроенным операторам (5 [expr]/3), если разрешение перегрузки выбирает перегруженный вызов функции для оператора, тогда вместо этого применяются ограничения для этого вызова функции.

Вот почему иногда рекомендуется возвращать объекты типа класса в виде const объектов (например, const foo q();), однако это может иметь негативное влияние на С++ 0x, где оно может препятствовать работе семантики перемещения, поскольку они следует.

Ответ 2

Так как structs можно назначить, а ваш q() возвращает копию struct foo, поэтому присваивает возвращенную структуру предоставленному значению.

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

Это имеет больше смысла (хотя все еще не является "лучшей практикой" )

struct foo
{
  int a;
};

foo* q() { foo *f = new malloc(sizeof(foo)); f->a = 4; return f; }

int main()
{
  foo i;
  i.a = 5;

  //sets the contents of the newly created foo
  //to the contents of your i variable
  (*(q())) = i;
}

Ответ 3

Одно интересное приложение:

void f(const std::string& x);
std::string g() { return "<tag>"; }

...

f(g() += "</tag>");

Здесь g() += изменяет временную, которая может быть быстрее, создавая дополнительное временное событие с +, потому что куча, выделенная для возвращаемого значения g(), может уже иметь достаточную запасную емкость для размещения </tag>.

Посмотрите, как он запускает на ideone.com с помощью GCC/С++ 11.

Теперь, какой компьютерный новичок сказал что-то о оптимизациях и зле...?; -.]