variable valores valor utilice una retornan referencia que punteros programacion programa por poner pase parametros mandar llamar llamadas funciones elabora como c++ c++11

valores - Interpretación de referencia en c++



parametros por referencia c++ (2)

En ambas llamadas a funciones, lo que se pasa a la función es un int & (en el sentido de: "un valor de tipo int "). Por lo tanto, ante la declaración de inc1 , el compilador debe deducir T modo que T && coincida con el argumento que proporcionó, es decir, int & . La única manera de hacer esto es asumir que T es int & , porque entonces T && es int & && , que es equivalente a int & . Entonces T convierte en int & y la y local se declara como tal.

Por otro lado, en inc2 , el compilador debe deducir T modo que T & coincida con el tipo de argumento que proporcionó, que todavía es int & . Es más fácil hacerlo asumiendo que T es simplemente int , así que eso es lo que se obtiene para el tipo de local y luego.

Responda a algunos comentarios (que mientras tanto se han eliminado): si tiene una función con un tipo de argumento predefinido, como

inc3(int x) { /*...*/ }

luego, cuando llama a esto, por ejemplo, como inc3(a) , el compilador aplicará la conversión implícita necesaria al argumento para que encaje. En el caso de inc3(a) esto significa transformar a de int & (en el sentido de lvalue) a int (en el sentido de rvalue), lo que se denomina conversión de lvalue a rvalue y una conversión implícita válida. Básicamente, equivale a transformar la variable a en el valor que representa en ese momento.

Pero cuando declara una plantilla , como inc1 e inc2 partir de la pregunta, y el argumento de función se define en términos de un parámetro de plantilla, el compilador no intentará, o no solo, aplicar conversiones implícitas al argumento para hacerlo ajuste. En su lugar, elegirá el parámetro de tipo de argumento T para que coincida con el tipo de argumento que proporcionó. Las reglas para esto son complicadas, pero en el caso de una declaración de argumento de tipo T && , funcionan como se describe anteriormente. (En el caso de una declaración de argumento T puro, un argumento lvalue todavía se someterá a conversión de valor lvalue a rvalue, y T se deducirá como int , no int & .)

Por eso, mientras que int && es una referencia de valor, T && (donde T es un parámetro de plantilla) no es necesariamente una referencia de valor. En cambio, es lo que resulte del ajuste de T al argumento proporcionado. Por lo tanto, la expresión T && en este caso se ha denominado referencia universal (como se opone a la referencia de valor lvalue o rvalue): es una referencia que se convierte en uno lvalue o rvalue, según sea necesario.

Considere el siguiente código:

#include <iostream> template<typename T> void inc1(T&& x) { T y = x; ++y; } template<typename T> void inc2(T& x) { T y = x; ++y; } int main() { int a = 10; inc1(a); // a is now 11 int b = 10; inc2(b); // b remains 10 }

Después de la sustitución tenemos

void inc1(int& x) { int& y = x; // reference to x ++y; // increments x } void inc2(int& x) { int y = x; // copy of x ++y; // increments the copie }

En inc1 , x es del tipo int& porque tanto int& como T&& son referencias pero no ambos son valores r.

De manera similar, en inc2 , x es del tipo int& , porque de nuevo, tanto int& como T& son referencias, pero no ambos son valores r.

Mi pregunta es acerca de y : ¿por qué en inc1 , y es de tipo int& , mientras que en inc2 , y es de tipo int ?

Observé esto tanto en gcc 4.8.1 como en microsoft v110 y v120_ctp.


S14.8.2.1 [temp.deduct.call] dice:

La deducción de los argumentos de la plantilla se realiza comparando cada tipo de parámetro de la plantilla de función (llámelo P) con el tipo del argumento correspondiente de la llamada (llámelo A) como se describe a continuación.

Entonces, estamos tratando de calcular una P dada A de tipo int .

S14.8.2.3 continúa:

Si P es un tipo calificado por el CV, los calificadores del CV de nivel superior del tipo P se ignoran para la deducción del tipo. Si P es un tipo de referencia, el tipo referido por P se usa para la deducción de tipo. Si P es una referencia de valor a un parámetro de plantilla no calificado de CV y ​​el argumento es un valor de l, se usa el tipo "referencia de valor de l a A" en lugar de A para la deducción de tipo. [Ejemplo:

template <class T> int f(T&&); // <--- YOUR TEMPLATE IS LIKE THIS template <class T> int g(const T&&); int i; int n1 = f(i); // calls f<int&>(int&) // <--- YOUR CALL IS LIKE THIS int n2 = f(0); // calls f<int>(int&&) int n3 = g(i); // error: would call g<int>(const int&&), which // would bind an rvalue reference to an lvalue

—En ejemplo]

Su llamada es como f(i) en el ejemplo, que ejemplifica una función de la forma f<int&>(int&) ... es decir, T es int& , por lo que T y = x crea una referencia a x .

Consulte también la página de Scott Meyers en http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers