2013-03-20 4 views
59

Qualcuno può dare un semplice esempio che dimostra la funzionalità di std::ref? Intendo un esempio in cui vengono utilizzati altri costrutti (come tuple o modelli di tipi di dati) solo se non è possibile spiegare std::ref senza di essi.Che cosa sarebbe un "Ciao, mondo!" esempio per "std :: ref"?

Ho trovato due domande su std::refhere e here. Ma nel primo si parla di un bug in un compilatore e nel secondo, gli esempi di utilizzo di std::ref non contengono std::ref e coinvolgono tuple e modelli di tipi di dati che rendono complessa la comprensione di questi esempi.

+4

http://en.cppreference.com/w/cpp/utility/functional/ref – inf

risposta

79

Si dovrebbe pensare di utilizzare std::ref quando una funzione:

  • prende un parametro modello per valore
  • o copie/muove un parametro inoltro di riferimento, come ad esempio std::bind o il costruttore per std::thread .

std::ref è un tipo di valore che si comporta come un riferimento.

Questo esempio consente l'uso dimostrabile di std::ref.

#include <iostream> 
#include <functional> 

void increment(int &x) 
{ 
    ++x; 
} 

int main() 
{ 
    int i = 0; 

    // Here, we bind increment to (a copy of) i... 
    std::bind(increment, i)(); 
    //      ^^ (...and invoke the resulting function object) 

    // i is still 0, because the copy was incremented. 
    std::cout << i << std::endl; 

    // Now, we bind increment to std::ref(i) 
    std::bind(increment, std::ref(i))(); 

    // i has now been incremented. 
    std::cout << i << std::endl; 
} 

uscita:

0 
1 
+3

Probabilmente vale la pena sottolineare che 'std :: ref' è riconciliabile, a differenza di un riferimento convenzionale, che può essere importante se ne stai alimentando uno in una funzione modello. Vedi http://stackoverflow.com/questions/37101301/is-this-stdref-behaviour-logical per un esempio. –

15
void PrintNumber(int i) {...} 

int n = 4; 
std::function<void()> print1 = std::bind(&PrintNumber, n); 
std::function<void()> print2 = std::bind(&PrintNumber, std::ref(n)); 

n = 5; 

print1(); //prints 4 
print2(); //prints 5 

std::ref viene utilizzato principalmente per incapsulare riferimenti utilizzando std::bind (ma altri usi sono possibili naturalmente).

6

Un altro posto in cui potrebbe essere necessario std :: ref è quando si passano oggetti ai thread in cui si desidera che ciascun thread funzioni sul singolo oggetto e non su una copia dell'oggetto.

int main(){ 
BoundedBuffer buffer(200); 

std::thread c1(consumer, 0, std::ref(buffer)); 
std::thread c2(consumer, 1, std::ref(buffer)); 
std::thread c3(consumer, 2, std::ref(buffer)); 
std::thread p1(producer, 0, std::ref(buffer)); 
std::thread p2(producer, 1, std::ref(buffer)); 

c1.join(); 
c2.join(); 
c3.join(); 
p1.join(); 
p2.join(); 

return 0; } 

dove si desidera che varie funzioni in esecuzione in vari thread condividano un singolo oggetto buffer. Questo esempio è stato rubato da questo eccellente tutorial (C++11 Concurrency Tutorial - Part 3: Advanced locking and condition variables (Baptiste Wicht) ) (spero di aver corretto correttamente l'attribuzione)

+0

Il motivo per usare 'std :: ref' qui, è costruttore di' thread' richiede un tipo di parametro 'std :: reference_wrapper' – Deqing