Quand l'utilisation de std:: ref est-elle nécessaire?
prendre en considération:
std::tuple<int , const A&> func (const A& a)
{
return std::make_tuple( 0 , std::ref(a) );
}
Est le std::ref
nécessaires à l'écriture correcte et code portable? (Il compile très bien sans elle)
Contexte:
si je supprime std::ref
mon code se construit bien sans aucun avertissement ( g++-4.6 -Wall
), mais ne fonctionne pas correctement.
en cas d'intérêt la définition de A
:
struct A {
std::array<int,2> vec;
typedef int type_t;
template<typename... OPs,typename... VALs>
A& operator=(const std::pair< std::tuple<VALs...> , std::tuple<OPs...> >& e) {
for( int i = 0 ; i < vec.size() ; ++i ) {
vec[i] = eval( extract(i,e.first) , e.second );
}
}
};
3 réponses
-
make_tuple(0, a)
fait untuple<int, A>
. -
make_tuple(0, ref(a))
fait untuple<int, reference_wrapper<A>>
. - vous pouvez aussi dire
tuple<int, A&> t(0, a);
pour un tuple que vous ne pouvez pas faire avecmake_tuple
, ou utiliserstd::tie
.
std::ref
ne fait pas de référence, donc dans votre exemple de code il ne fait pas ce que vous attendez. std::ref
crée un objet qui se comporte comme une référence. Il peut être utile, par exemple, lorsque vous voulez instancier un functor, et passer une version de référence de celui-ci à un algorithme de bibliothèque standard. Puisque les algorithmes prennent les foncteurs en valeur, vous pouvez utiliser std::ref
pour envelopper le foncteur.
L'un des exemples où std::ref
est nécessaire:
void update(int &data) //expects a reference to int
{
data = 15;
}
int main()
{
int data = 10;
// This doesn't compile as the data value is copied when its reference is expected.
//std::thread t1(update, data);
std::thread t1(update, std::ref(data)); // works
t1.join();
return 0;
}
le constructeur std::thread
copie les valeurs fournies telles quelles, sans passer au type d'argument attendu (qui est référence type dans ce cas, voir update()
). Nous devons donc envelopper les arguments qui ont vraiment besoin d'être des références dans std::ref
.