2011-10-22 1584 views
11

Hay tal código:Cambio de valor de retorno de tipo fundamental y el tipo de clase

#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; 
} 

¿Por qué es posible cambiar el valor de retorno de std :: string, pero no int?

Respuesta

10

porque std::string es un tipo de clase con un operador += definido como función de miembro.

y el estándar le permite llamar a las funciones miembro en rvalues.

consecuencia tonta de ello es que

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. 
} 

resultados de compilación:

 
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". 

Sin embargo, los compiladores diferentes (o se utilizan para variar) acerca de lo estricta que aplican esta regla sutil, o como mucho.

aplausos & HTH.,

+0

Bueno, pero para 'int' el operador' + = 'también está definido. – Vlad

+0

@downvoter: ¿Por qué? – Vlad

+0

@anonymous downvoter: explique su voto negativo para que otros puedan beneficiarse de su visión, o ignore alguna razón estúpida. –

2

El lado izquierdo de un operador de asignación para un valor p tipo incorporado debe ser modificable lvalue pero el valor de retorno de una función es siempre una si la función no devuelve un tipo de referencia.

operator+= es una función miembro de std::string y se puede llamar a una función miembro de una rvalue del tipo de clase.

+0

Me pregunto, ¿por qué tal inconsistencia? – Vlad

+0

¿Quisiste decir "lado izquierdo de un operador de asignación"? –

+0

@VaughnCato: Sí, lo hice. Gracias. –

1

Por la misma razón

std::string("siema") += "cze"; 

obras.

Está construyendo un objeto nuevo y aplicando el operator += (que tiene std::string).

Probar esto con él no funcionará ya que su función devuelve rvalue. Sería como:

2 += 2 

Usted puede juguetear con esto:

#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; 
} 

Pero esto conducirá a una pérdida de memoria, así que no lo haga. Es solo una prueba de concepto que devolver un lvalue funcionaría.

+0

Hola Luchian :) ¿'' returntext' no devuelve un valor rvalue también? – Vlad

+0

Charles Bailey ha escrito: pero el valor de retorno de una función es siempre un valor r si la función no devuelve un tipo de referencia. Entonces returntext devuelve rvalue o lvalue? – scdmb

+0

Estoy confundido, listo para leer :) –

0

returntext() devuelve un std::string que se puede modificar en etapas posteriores, por ejemplo, con +=operator. Sin embargo, aunque returnnumber() devuelve un int, la función en sí está devolviendo 2 que es por definición un const int y no es modificable y es por eso que el compilador se queja.

Cuestiones relacionadas