descargar - ¿Inicialización no válida de referencia no constante con subproceso C++ 11?
c++17 descargar (2)
Ajuste x
en std::ref
cuando cree el hilo.
Si cada vez que creara un std::thread
tomaba todas las variables por referencia, piense qué pasaría: si pasara una variable local de stack, sería una referencia pendiente, y se produciría un comportamiento indefinido si el thread sobreviviera al alcance de esa variable de almacenamiento automático. Esto sucedería mucho en la práctica, y daría lugar a muchos errores. En su lugar, std::thread
por defecto toma (califica a través del reenvío perfecto) todos los argumentos (incluidas las variables) por valor.
El std::future
podría funcionar silenciosamente al llamar a su función de trabajador al pasar una copia de lvalue local de subproceso de x
, pero eso sería bastante confuso: la tarea de trabajador editaría x
que usted pensó que pasó por referencia, y no lo haría t aparece en la x
fuera de la tarea. En su lugar, le da útil ese mensaje de error. ¡Deberías agradecer a tus afortunadas estrellas por ello!
Para indicar que realmente desea no tomar algo por valor, envuélvalo en std::ref
, y ahora se pasa a la función de trabajo como referencia. En este caso, usted es responsable de administrar el tiempo de vida de la referencia para que la información a la que se hace referencia dure al menos mientras la tarea del trabajador de std::future
la necesite.
Estoy recibiendo un error sobre
error: inicialización no válida de referencia no constante de tipo ''int &'' a partir de un valor de tipo ''int''
desde
#include <thread>
#include <iostream>
using namespace std;
void func(int& i){
cout<<++i<<endl;
}
int main(){
int x=7;
thread t(func,x);
t.join();
return 0;
}
Entiendo que no puedo hacer thread(func, 4)
pero x
es una variable, no una temporal.
Estoy usando gcc 4.7 con -std = c ++ 11 -pthread
¿Por qué está ocurriendo este error?
La especificación para el constructor std::thread
dice
Efectos: construye un objeto de tipo hilo. El nuevo hilo de ejecución ejecuta INVOKE
(
DECAY_COPY( std::forward<F>(f)),
DECAY_COPY(std::forward<Args>(args))...)
con las llamadas a DECAY_COPY evaluadas en el hilo de construcción. .
Donde DECAY_COPY (x) significa llamar a decay_copy(x)
donde se define como:
template <class T> typename decay<T>::type decay_copy(T&& v)
{ return std::forward<T>(v); }
Lo que esto significa es que los argumentos "decaen" y se copian, lo que significa que se reenvían por valor y pierden cualquier calificación cv. Debido a que la función de destino ejecutada por el hilo quiere tomar su parámetro por referencia , se obtiene un error del compilador que indica que la referencia no puede vincularse a un objeto pasado por valor.
Esto es por diseño, de modo que, de forma predeterminada, las variables locales pasadas a un std::thread
se pasan por valor (es decir, se copian) no por referencia, de modo que el nuevo thread no tenga referencias pendientes a variables locales que queden fuera del alcance, lo que lleva a al comportamiento indefinido.
Si sabe que es seguro pasar las variables por referencia, entonces debe hacerlo explícitamente, utilizando un reference_wrapper
que no se verá afectado por la semántica de "decaimiento" y reenviará la variable por referencia al objeto objetivo. Puedes crear un reference_wrapper
usando std::ref
.