通过编译错误 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!
}
我们定义了一个Widget
class和WidgetGuard
class来模拟std::mutex
和std::lock_guard
。当我们尝试用括号声明一个临时的 WidgetGuard
时,它会报错。但是用大括号编译。
这可以用实验1来解释。编译器将WidgetGuard{ w1 }
解析为"create temporary"。但是它将 WidgetGuard(w1)
解析为 "declare variable w1
"!错误来源有两个:重复使用相同的名称,以及 WidgetGuard
.
中没有默认构造函数
实验 0
回到std::mutex
和std::lock_guard
,让我们试试大括号...
std::mutex m;
std::lock_guard<std::mutex> {m};
...而且有效。
可以创建 std::lock_guard
的临时文件。我们就是可以。
当一个人在 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!
}
我们定义了一个Widget
class和WidgetGuard
class来模拟std::mutex
和std::lock_guard
。当我们尝试用括号声明一个临时的 WidgetGuard
时,它会报错。但是用大括号编译。
这可以用实验1来解释。编译器将WidgetGuard{ w1 }
解析为"create temporary"。但是它将 WidgetGuard(w1)
解析为 "declare variable w1
"!错误来源有两个:重复使用相同的名称,以及 WidgetGuard
.
实验 0
回到std::mutex
和std::lock_guard
,让我们试试大括号...
std::mutex m;
std::lock_guard<std::mutex> {m};
...而且有效。
可以创建 std::lock_guard
的临时文件。我们就是可以。