sociologia segun origen memetica memes meme los importancia fenomeno ensayo definicion comunicacion autores analisis c++ c++11

c++ - segun - meme y memetica



C++ 11: ¿Mover/Copiar la ambigüedad de la construcción? (4)

En C ++ 11 podemos definir los constructores de copiar y mover, pero ¿ambos están permitidos en la misma clase? Si es así, ¿cómo se desmarca su uso? Por ejemplo:

Foo MoveAFoo() { Foo f; return f; }

¿Lo de arriba es una copia? ¿Un movimiento? ¿Cómo puedo saber?


La "desambiguación" es solo tu viejo amigo, resolución de sobrecarga:

Foo y; Foo x(y); // copy Foo x(std::move(y)); // move

La expresión y en el primer ejemplo es un lvalor de tipo Foo , que se enlaza con Foo const & (y también Foo & si tiene un constructor de este tipo); El tipo de expresión std::move(y) en el segundo ejemplo es Foo && , por lo que se unirá a Foo && (y también a Foo const & absent the first).

En su ejemplo, el resultado de MoveAFoo() es un temporal de tipo Foo , por lo que se vinculará al Foo && -constructor si hay uno disponible, y a un constructor de copia constante de lo contrario.

Finalmente, en una función que devuelve Foo (por valor), la instrucción return x; es equivalente a return std::move(x); si x es una variable local de tipo Foo , esta es una nueva regla especial para facilitar el uso de la semántica de movimientos.


Para hacer una copia de seguridad de @Seth, aquí está el párrafo relevante de la norma:

§12.8 [class.copy] p32

Cuando los criterios para la elección de una operación de copia se cumplen o se cumplirían, salvo por el hecho de que el objeto fuente es un parámetro de función, y el objeto que se va a copiar se designa mediante un lvalor, la resolución de sobrecarga para seleccionar el constructor para la copia Primero se realiza como si el objeto fuera designado por un valor de r . Si la resolución de sobrecarga falla, o si el tipo del primer parámetro del constructor seleccionado no es una referencia de valor al tipo del objeto (posiblemente cv-calificado), la resolución de sobrecarga se realiza nuevamente, considerando el objeto como un valor de l. [ Nota: esta resolución de sobrecarga de dos etapas se debe realizar independientemente de si se producirá elision de copia. Determina el constructor que se llamará si no se realiza el elision, y el constructor seleccionado debe ser accesible incluso si la llamada es eluida. "Nota final "


Por lo general, no será debido a RVO .

Si esa optimización no se puede realizar, entonces será un movimiento, porque el objeto que se devuelve está fuera del alcance (y se destruirá justo después). Si no se puede mover, se copiará. Si no se puede copiar, no se compilará.

El punto central de los constructores de movimientos es que cuando se va a hacer una copia de un objeto que está a punto de ser destruido, a menudo no es necesario hacer una copia completa, y los recursos se pueden mover del objeto moribundo al objeto. siendo creado en su lugar.

Puede saber cuándo se llamará al constructor de copia o movimiento según lo que sucederá con el objeto que se está moviendo / copiando. ¿Está a punto de salir de alcance y ser destruido? Si es así, se llamará al constructor de movimientos. Si no, el constructor copia.

Naturalmente, esto significa que puede tener un constructor de movimiento y un constructor de copia en la misma clase. También puede tener un operador de asignación de copia y un operador de asignación de movimiento también.

Actualización: puede no estar claro exactamente cuándo se llama al constructor de movimiento / operador de asignación frente al constructor de copia plana / operador de asignación. Si entiendo correctamente, se llama al constructor de movimiento si un objeto se inicializa con un xvalue (valor eXpiring). §3.10.1 de la norma dice

Un xvalue (un valor "eXpiring") también se refiere a un objeto, generalmente cerca del final de su vida útil (por ejemplo, para poder mover sus recursos). Un xvalue es el resultado de ciertos tipos de expresiones que involucran referencias de rvalue (8.3.2). [Ejemplo: el resultado de llamar a una función cuyo tipo de retorno es una referencia rvalue es un xvalue. —En ejemplo]

Y el comienzo del §5 de la norma dice:

[Nota: una expresión es un valor x si es:

  • el resultado de llamar a una función, ya sea implícita o explícitamente, cuyo tipo de retorno es una referencia rvalue al tipo de objeto,
  • una conversión a una referencia rvalue al tipo de objeto,
  • una expresión de acceso de miembro de clase que designa un miembro de datos no estáticos de tipo no de referencia en el que la expresión de objeto es un valor x, o
  • Una expresión de. * puntero a miembro en la que el primer operando es un xvalue y el segundo es un puntero al miembro de datos.

En general, el efecto de esta regla es que las referencias de rvalue con nombre se tratan como lvalues ​​y las referencias de rvalue sin nombre a los objetos se tratan como xvalues; Las referencias de rvalue a las funciones se tratan como lvalues ​​ya sea nombrados o no. "Nota final"

Como ejemplo, si se puede hacer NRVO, es como esto:

void MoveAFoo(Foo* f) { new (f) Foo; } Foo myfoo; // pretend this isn''t default constructed MoveAFoo(&myfoo);

Si no se puede hacer NRVO pero Foo es movible, entonces su ejemplo es un poco como este:

void MoveAFoo(Foo* fparam) { Foo f; new (fparam) Foo(std::move(f)); } Foo f; // pretend this isn''t being default constructed MoveAFoo(&f);

Y si no se puede mover pero se puede copiar, entonces es así

void MoveAFoo(Foo* fparam) { Foo f; new (fparam) Foo((Foo&)f); } Foo f; // pretend this isn''t default constructed MoveAFoo(&f);


Foo MoveAFoo() { Foo f; return f; }

Esta es la definición de la función MoveAFoo que devuelve el objeto de tipo Foo . En su cuerpo local Foo f; Se crea y se destruye cuando se sale de su alcance.

En este código:

Foo x = MoveAFoo();

objeto Foo f; se crea dentro de la función MoveAFoo y se asigna directamente a x , lo que significa que no se llama al constructor de copia.

Pero en este código:

Foo x; x = MoveAFoo();

objeto Foo f; se crea dentro de la función MoveAFoo , luego la copia de f se crea y almacena en x f original se destruye.