【问题标题】:How to instantiate an "empty" object from a class that provides only copy-constructor?如何从仅提供复制构造函数的类中实例化“空”对象?
【发布时间】:2014-09-17 12:47:00
【问题描述】:

我实现了一个线程安全的模板化队列:

template<class T> class queue {

private:    
    boost::mutex mutex;
    boost::condition_variable emptyCondition;
    boost::condition_variable fullCondition;

    boost::scoped_ptr< std::queue<T> > std_queue;
     ...

public:
   ...

  T pop() {
        T r; // [*]
        {
            boost::mutex::scoped_lock popLock(mutex);
            while (queueIsEmpty())
                emptyCondition.wait(popLock);

            r = std_queue->front();
            std_queue->pop();
        }

        fullCondition.notify_one();    
        return r;
    }
     ...

由于缺少 T 的构造函数,没有形式参数,我无法以我的方式实例化对象(标记为 [*])。

那么:有没有办法,可能使用指向T 的指针和复制构造函数(我知道它是为每个T 实现的)来避免许多模板特化?

编辑 1

我也想过这个可能的解决方案。

T pop() {
    boost::mutex::scoped_lock popLock(mutex);
    while (queueIsEmpty())
        emptyCondition.wait(popLock);

    T r(std_queue->front());
    std_queue->pop();

    // update overall number of pop
    popNo++;

    popLock.unlock();
    fullCondition.notify_one();
    return r;
}

它会起作用吗?

【问题讨论】:

    标签: c++ boost stl queue condition-variable


    【解决方案1】:

    这种情况的一个选项是使用boost::optional

    T pop() {
        boost::optional<T> r;
        {
            boost::mutex::scoped_lock popLock(mutex);
            while (queueIsEmpty())
                emptyCondition.wait(popLock);
    
            r = std_queue->front();
            std_queue->pop();
        }
    
        fullCondition.notify_one();    
        return *r;  // r is guaranteed to be engaged at this point
    }
    

    boost::optional 在运行时负责跟踪其包含的T 是否已构建,以及是否需要销毁。 (注意这里你实际上并不需要boost::mutex::scoped_lock; you can useboost::lock_guard`的全部功能。)

    另一种方法是注意scoped_lock可以被释放:

    T pop() {
        boost::mutex::scoped_lock popLock(mutex);
        while (queueIsEmpty())
            emptyCondition.wait(popLock);
    
        T r = std_queue->front();
        std_queue->pop();
        popLock.release();
    
        fullCondition.notify_one();    
        return r;
    }
    

    这里的缺点是不太清楚popLock的范围是什么,代码更改可能会导致代码不安全或死锁。

    【讨论】:

    • 如果你解释为什么它是最好的选择你会得到一个赞成票,否则 jquery 太多
    【解决方案2】:

    如果您手动解锁,则可以摆脱括号,从而无需预先创建 T:

    T pop() {
       boost::mutex::scoped_lock popLock(mutex);
       while (queueIsEmpty())
          emptyCondition.wait(popLock);
    
       T r = std_queue->front();
       std_queue->pop();
       popLock.unlock();
    
       fullCondition.notify_one();    
       return r;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-28
      • 1970-01-01
      • 2012-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-25
      相关资源
      最近更新 更多