Изменение возвращаемого значения основного типа и типа класса

Существует такой код:

#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, и не может быть изменена и что компилятор жалуется.