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

Forcing non-temporary in RAII by compile Error C++

当一个人在 C++ 中像这样使用 lock_guard 时:

 lock_guard<mutex>(lock);

编译器抱怨:

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

因为正确的用法是:

 lock_guard<mutex> guard(lock);

我想编写一个自定义的 RAII 分配器,它在发生这种情况时也会发出警告 - 我尝试禁用复制构造函数和赋值运算符,但到目前为止没有任何效果。

我不知道如何实现你的目标,但我想我知道 lock_guard<mutex>(lock).

发生了什么

让我们做一些实验。

实验 1

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

实验表明我们已经声明了一个变量x,即使有一对括号。

实验二

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

我们定义了一个Widgetclass和WidgetGuardclass来模拟std::mutexstd::lock_guard。当我们尝试用括号声明一个临时的 WidgetGuard 时,它会报错。但是用大括号编译。

这可以用实验1来解释。编译器将WidgetGuard{ w1 }解析为"create temporary"。但是它将 WidgetGuard(w1) 解析为 "declare variable w1"!错误来源有两个:重复使用相同的名称,以及 WidgetGuard.

中没有默认构造函数

实验 0

回到std::mutexstd::lock_guard,让我们试试大括号...

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

...而且有效。

可以创建 std::lock_guard 的临时文件。我们就是可以。