77

有人可以举一个简单的例子来演示它的功能std::ref吗?我的意思是一个例子,其中一些其他构造(如元组或数据类型模板)仅在没有它们就无法解释的情况下使用std::ref

我发现了两个关于std::ref 这里这里的问题。但是在第一个中,它涉及编译器中的一个错误,而在第二个中,使用的示例std::ref不包含std::ref,它们涉及元组和数据类型模板,这使得对这些示例的理解变得复杂。

4

4 回答 4

93

您应该考虑使用std::refwhen 函数:

  • 按值获取模板参数
  • 复制/移动模板参数,例如std::bind或 的构造函数std::thread

std::ref创建一个行为类似于引用的可复制值类型。

这个例子演示了使用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;
}

输出:

0
1
2
于 2013-03-20T17:27:11.690 回答
16
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(当然其他用途也是可以的)。

于 2013-03-20T17:29:25.557 回答
9

您可能需要 std::ref 的另一个地方是将对象传递给您希望每个线程对单个对象而不是对象的副本进行操作的线程时。

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 并发教程 - 第 3 部分:高级锁定和条件变量(Baptiste Wicht) )中偷来的(希望我正确地做了归属)

于 2015-03-10T17:27:22.977 回答
0

// 生产者消费者问题

#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只是在 main 中使用 std::ref 的另一种用法,同时在生产者和消费者中传递对象作为引用。如果std::ref不使用,则此代码将无法编译。

于 2019-05-22T15:44:33.000 回答