C++: является ли возвращаемое значение L-значением?


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

struct foo
{
  int a;
};

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

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

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

3 66

3 ответа:

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

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

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

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

потому что структуры могут быть присвоены, и ваш 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;
}

одно интересное применение этого:

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

...

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

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

запустить at ideone.com с GCC / C++11.

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