Diferença entre ponteiro e referência como parâmetro de thread

Este é o exemplo:

#include #include using namespace std; void f1(double& ret) { ret=5.; } void f2(double* ret) { *ret=5.; } int main() { double ret=0.; thread t1(f1, ret); t1.join(); cout << "ret=" << ret << endl; thread t2(f2, &ret); t2.join(); cout << "ret=" << ret << endl; } 

E a saída é:

 ret=0 ret=5 

Compilado com o gcc 4.5.2, com e sem -O2

Esse comportamento é esperado?

Esta corrida de dados do programa é gratuita?

Obrigado

O construtor de std::thread deduz os tipos de argumentos e armazena cópias deles por valor. Isso é necessário para garantir que o tempo de vida do object de argumento seja pelo menos igual ao do segmento.

Mecanismo de dedução de tipo de argumento de function modelo C ++ deduz o tipo T de um argumento do tipo T& . Todos os argumentos para std::thread são copiados e depois passados ​​para a function de thread, de modo que f1() e f2() sempre usem essa cópia.

Se você insistir em usar uma referência, coloque o argumento usando boost::ref() ou std::ref() :

 thread t1(f1, boost::ref(ret)); 

Ou, se preferir a simplicidade, passe um ponteiro. Isto é o que boost::ref() ou std::ref() faz por você por trás da cena.

O fato de você precisar de um std::ref() (ou boost::ref() ) explícito nessas situações é, na verdade, um recurso de segurança muito útil, pois a passagem de uma referência pode ser, por natureza, algo perigoso a ser feito.

Com uma referência não-const, muitas vezes há um perigo que você está passando em uma variável local, com uma referência const pode ser um temporário, e como você está criando uma function para ser chamada em um thread diferente (e com bind em geral, muitas vezes uma function a ser chamada posteriormente / de maneira assíncrona) você terá o grande perigo de o object não ser mais válido.

vinculação parece arrumado, mas esses bugs são os mais difíceis de encontrar, como onde o erro é capturado (ou seja, chamando a function) não é o mesmo lugar que o erro foi feito (no momento da binding) e pode ser muito difícil de trabalhar exatamente qual function está sendo chamada no momento e, portanto, onde foi ligada.

É seguro em sua instância quando você une o encadeamento no escopo da variável que você está passando como referência. Portanto, quando você sabe que, para ser o caso, existe um mecanismo para passar uma referência.

Não é uma característica da linguagem que eu gostaria de ver alterada, particularmente porque há provavelmente muito código existente contando com uma cópia que seria quebrada se fosse tomada automaticamente por referência (e então precisaria de uma maneira explícita de forçar uma cópia).

Se você quiser passar parâmetros por referência a um std::thread você deve colocar cada um deles em std::ref :

 thread t1(f1, std::ref(ret)); 

Mais informações aqui .