web-dev-qa-db-ja.com

「Hello、World!」 「std :: ref」の例?

誰かがstd::refの機能を示す簡単な例を挙げられますか?他のいくつかの構成要素(タプルやデータ型テンプレートなど)が使用されている例は、それらなしではstd::refを説明することができない場合に限られます。

std::refherehere について2つの質問が見つかりました。しかし、1つ目はコンパイラのバグに関する問題で、2つ目はstd::refの使用例にstd::refが含まれておらず、これらの例を理解するタプルとデータ型テンプレートが含まれています。繁雑。

66
Roman

関数の場合は std::ref の使用を検討する必要があります。

  • 値によるテンプレートパラメータを取ります
  • または転送参照パラメーターをコピーまたは移動します std::bind または std::thread のコンストラクターなど。

std::refは、参照のように動作する値型です。

この例では、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;
}

出力:

0
1
81
Drew Dormann
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は、std::bindを使用するときに参照をカプセル化するために主に使用されます(ただし、他の使用法ももちろん可能です)。

15
sbabbi

Std :: refが必要になる可能性のあるもう1つの場所は、各スレッドがオブジェクトのコピーではなく単一のオブジェクトを操作するようにスレッドにオブジェクトを渡す場合です。

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

さまざまなスレッドで実行されているさまざまな関数が単一のバッファオブジェクトを共有するようにする場合。この例は、この優れたチュートリアルから盗まれました( C++ 11 Concurrency Tutorial-Part 3:Advanced Locking and Condition Variables(Baptiste Wicht) )(私が正しく帰属したことを願っています)

7
bd2357

//生産者の消費者問題

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

プロデューサーとコンシューマーの参照としてBufferオブジェクトを渡すときに、メインでstd :: refをもう1つ使用します。 std::ref使用しない場合、このコードはコンパイルされません。

0
Rupesh Yadav.