Рассмотрим этот код:
struct foo
{
int a;
};
foo q() { foo f; f.a =4; return f;}
int main()
{
foo i;
i.a = 5;
q() = i;
}
Ни один компилятор не жалуется на это, даже Clang. Почему строка q() = ...
правильная?
Рассмотрим этот код:
struct foo
{
int a;
};
foo q() { foo f; f.a =4; return f;}
int main()
{
foo i;
i.a = 5;
q() = i;
}
Ни один компилятор не жалуется на это, даже Clang. Почему строка q() = ...
правильная?
Нет, возвращаемое значение функции является l-значением тогда и только тогда, когда оно является ссылкой (C++03). (5.2.2 [экспр.вызов] / 10)
Если бы возвращаемый тип был базовым типом, это было бы ошибкой компиляции. (5,17 [выраж.зад] / 1)
Причина, по которой это работает, заключается в том, что вам разрешено вызывать функции-члены (даже не-1_ функции-члены) для r-значений типа класса, а назначение foo
является функцией-членом, определенной реализацией: foo& foo::operator=(const foo&)
. Ограничения для операторов в разделе 5 применяются только к встроенным операторам, (5 [expr] / 3), если разрешение перегрузки выбирает вызов перегруженной функции для оператора, тогда применяются ограничения для этого вызова функции. вместо.
Вот почему иногда рекомендуется возвращать объекты типа класса как объекты const
(например, const foo q();
), однако это может иметь негативные последствия в C++0x, где это может помешать семантике перемещения работать должным образом.
std::cout << "Hello, world" << std::endl
. Первый operator<< ()
возвращает lvalue, по которому вы можете вызвать второй operator<< ()
. Таким образом, эта практика вызова методов для возвращаемых значений более распространена, чем многие думают.
- person MSalters; 24.05.2011
The Design and Evolution of C++
: Это источник идеи, которая с годами превратилась в эмпирическое правило для разработки C++: определяемые пользователем и встроенные типы должны вести себя одинаково по отношению к правила языка и получают такую же степень поддержки со стороны языка и связанных с ним инструментов. Когда идеал был сформулирован, встроенные типы получили наилучшую поддержку, но C++ перевыполнил эту цель, так что теперь встроенные типы получают несколько меньшую поддержку по сравнению с типами, определяемыми пользователем.
- person Seth Carnegie; 24.05.2011
cout
он на самом деле возвращает lvalue (он возвращает себя и по ссылке, *this
), а не что-то по значению. Так что это немного другое.
- person Seth Carnegie; 24.05.2011
std::cout << "duh" << std::endl
все operator<<
возвращают неконстантные ссылки (которые являются lvalues), и поскольку все операторы требуют неконстантных ссылок в качестве своего первого параметра, исходный объект std::ostream
не может быть rvalue. В других примерах (и я предполагаю, что это мотивация вопроса) неконстантные функции вызываются временно.
- person James Kanze; 24.05.2011
q().operator=(i)
на самом деле не такое уж исключение.
- person MSalters; 26.05.2011
Поскольку структуры могут быть назначены, и ваш 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;
}
int blah() { int f = 4; return f; } int main() { int a = 99; blah() = a; }
есть ли что-то волшебное в структурах? Потому что этот код не компилируется.
- person Seth Carnegie; 24.05.2011
int::operator=(int)
. Это волшебная часть структур: у них есть методы по умолчанию.
- person MSalters; 24.05.2011
s/nothing/anything/
- person Lightness Races in Orbit; 24.05.2011
Одно интересное применение этого:
void f(const std::string& x);
std::string g() { return "<tag>"; }
...
f(g() += "</tag>");
Здесь g() +=
изменяет временное, что может быть быстрее, чем создание дополнительного временного с помощью +
, потому что куча, выделенная для возвращаемого значения g(), может уже иметь достаточную свободную емкость для размещения </tag>
.
Посмотрите, как он работает на ideone.com с GCC/C++11.
Итак, кто из новичков в вычислительной технике сказал что-то об оптимизации и зле...? ;-].
q()
возвращает структуру, а затем вы присваиваете ей значение. Что в этом плохого? - person Andy Johnson   schedule 24.05.2011