通过编译Error C ++在RAII中强制非临时

时间:2015-03-12 03:34:57

标签: c++ raii most-vexing-parse

当在C ++中使用lock_guard时,如下所示:

 lock_guard<mutex>(lock);

编译器抱怨:

no matching constructor for initialization of 'std::lock_guard<std::mutex>'

因为正确使用是:

 lock_guard<mutex> guard(lock);

我想编写一个自定义RAII分配器,当这种情况发生时也会同时发生 - 我尝试禁用复制consturctor和assigment运算符,但到目前为止没有任何作用。

1 个答案:

答案 0 :(得分:3)

我不知道如何实现目标,但我想我知道lock_guard<mutex>(lock)发生了什么。

让我们做一些实验。

实验1

int(x);
x = 1;
std::cout << x << std::endl;

实验显示我们已声明变量x,即使有一对括号。

实验2

class Widget
{
};

class WidgetGuard
{
private:
    Widget& widget;
public:
    WidgetGuard(Widget& w)
        : widget(w)
    {}
};

int main()
{
    Widget w1;

    WidgetGuard wg1(w1);
    WidgetGuard(w1);     //Error!
    WidgetGuard{ w1 };   //Pass!
}

我们定义Widget类和WidgetGuard类来模拟std::mutexstd::lock_guard。当我们尝试使用括号声明临时WidgetGuard时,会出错。但是使用大括号进行编译。

这可以用实验1解释。编译器解析WidgetGuard{ w1 }为&#34;创建临时&#34;。但它解析WidgetGuard(w1)为&#34;声明变量w1&#34;!有两个错误来源:重用相同的名称,WidgetGuard中没有默认构造函数。

实验0

返回std::mutexstd::lock_guard,让我们尝试一下......

std::mutex m;
std::lock_guard<std::mutex> {m};

......它有效。

可以创建临时std::lock_guard。我们可以。