Изменение возвращаемого значения основного типа и типа класса
Существует такой код:
#include <iostream>
#include <string>
int returnnumber() { return 2; }
std::string returntext() { return "siema"; }
int main() {
std::cout << (returntext() += "cze") << std::endl; // siemacze
//std::cout << (returnnumber() += 2) << std::endl; error: lvalue required as left operand of assignment
return 0;
}
Почему возможно изменить возвращаемое значение std::string, но не int?
Ответы
Ответ 1
поскольку std::string
- это тип класса с определенным оператором +=
в качестве функции-члена.
и стандарт позволяет вам вызывать функции-члены на r-значениях.
глупым следствием этого является то, что
struct S { int x; };
S foo() { return S(); }
int main()
{
foo() = S(); // OK, uses member assignment operator.
foo().x = 666; // !Nah, can't assign to rvalue of built-in type.
}
результаты компиляции:
Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions
"ComeauTest.c", line 7: error: expression must be a modifiable lvalue
foo().x = 666; // !Nah, can't assign to rvalue of built-in type.
^
1 error detected in the compilation of "ComeauTest.c".
однако, компиляторы отличаются (или отличаются друг от друга) тем, насколько строго они применяли это тонкое правило, или если вообще.
приветствия и hth.,
Ответ 2
Левая часть оператора присваивания для встроенного типа должна быть модифицируемой переменной lvalue, но возвращаемое значение функции всегда является rvalue, если функция не возвращает ссылочный тип.
operator+=
является функцией-членом std::string
, и вы можете вызвать функцию-член в r-значении типа класса.
Ответ 3
По той же причине
std::string("siema") += "cze";
работы.
Вы создаете новый объект и применяете к нему operator +=
(который std::string
).
Попытка этого с ним не будет работать, так как ваша функция возвращает rvalue
. Это было бы так:
2 += 2
Вы можете играть с этим:
#include <iostream>
#include <string>
int& returnnumber() { int * k = new int; *k = 2; return *k; }
std::string returntext() { return "siema"; }
int main() {
std::cout << (returntext() += "cze") << std::endl; // siemacze
std::cout << (returnnumber() += 2) << std::endl; //no error
std::string("siema") += "cze";
return 0;
}
Но это приведет к утечке памяти, поэтому не делайте этого. Это просто доказательство того, что возвращение lvalue
будет работать.
Ответ 4
returntext()
возвращает a std::string
, который можно изменить на более поздних этапах, скажем, с помощью +=operator
. Однако, хотя returnnumber()
возвращает int
, сама функция возвращает 2
, которая определяется defualt a const int
, и не может быть изменена и что компилятор жалуется.