82 votes

Quel serait un exemple de "Hello, World !" pour "std::ref" ?

Quelqu'un peut-il donner un exemple simple qui démontre la fonctionnalité de std::ref ? Je veux dire un exemple dans lequel d'autres constructions (comme les tuples, ou les modèles de type de données) sont utilisées. seulement si il est impossible d'expliquer std::ref sans eux.

J'ai trouvé deux questions sur std::ref aquí y aquí . Mais dans le premier, il est question d'un bug dans un compilateur et dans le second, d'exemples d'utilisation de std::ref ne contiennent pas std::ref et ils impliquent des tuples et des modèles de types de données qui rendent la compréhension de ces exemples complexe.

98voto

Drew Dormann Points 25025

Vous devriez penser à utiliser std::ref quand une fonction :

  • prend un paramètre de modèle par valeur
  • copie/déplace un paramètre de modèle comme std::bind ou le constructeur de std::thread .

std::ref crée un type de valeur copiable qui se comporte comme une référence.

Cet exemple fait un usage démontrable de std::ref .

#include <iostream>
#include <functional>
#include <thread>

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;

  // The same applies for std::thread
  std::thread( increment, std::ref(i) ).join();
  std::cout << i << std::endl;
}

Sortie :

0
1
2

16voto

sbabbi Points 3366
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 est principalement utilisé pour encapsuler les références lors de l'utilisation de l'outil std::bind (mais d'autres utilisations sont possibles bien sûr).

10voto

bd2357 Points 152

Un autre endroit où vous pouvez avoir besoin de std::ref est lorsque vous passez des objets à des threads où vous voulez que chaque thread opère sur l'objet unique et non sur une copie de l'objet.

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; }

où vous souhaitez que plusieurs fonctions exécutées dans différents threads partagent un seul objet tampon. Cet exemple a été volé à cet excellent tutoriel ( Tutoriel sur la concurence en C++11 - Partie 3 : verrouillage avancé et variables de condition (Baptiste Wicht) ) (j'espère que l'attribution est correcte)

0voto

Rupesh Yadav. Points 693

// Problème du producteur et du consommateur

#include <iostream>
#include <thread>
#include <mutex>
#include <deque>
#include <condition_variable>
using namespace std;

class Buffer {

    std::mutex m;
    std::condition_variable cv;
    std::deque<int> queue;
    const unsigned long size = 1000;

    public:
    void addNum(int num) {
        std::unique_lock<std::mutex> lock(m);
        cv.wait(lock, [this]() { return queue.size() <= size; });
        queue.push_back(num);
        cout << "Pushed " << num << endl;
        lock.unlock();
        cv.notify_all();
    }
    int removeNum() {
        std::unique_lock<std::mutex> lock(m);
        cv.wait(lock, [this]() { return queue.size()>0; });
        int num = queue.back();
        queue.pop_back();
        cout << "Poped " << num << endl;
        lock.unlock();
        cv.notify_all();
        return num;
    }

};

void producer(int val, Buffer& buf) {
    for(int i=0; i<val; ++i){
        buf.addNum(i);
    }
}

void consumer(int val, Buffer& buf){
    for(int i=0; i<val; ++i){
        buf.removeNum();
    }
}

int main() {
    Buffer b;
    std::thread t1(producer, 1000, std::ref(b));
    std::thread t2(consumer, 1000, std::ref(b));

    t1.join();
    t2.join();
    return 0;
}

Juste une autre utilisation de std::ref dans main tout en passant Buffer comme référence dans le producteur et le consommateur. Si std::ref n'est pas utilisé, alors ce code ne sera pas compilé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X