Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;声明RAII类型的推荐方式(唯一锁定)_C++_Syntax - Fatal编程技术网

C++ C++;声明RAII类型的推荐方式(唯一锁定)

C++ C++;声明RAII类型的推荐方式(唯一锁定),c++,syntax,C++,Syntax,今天我无意中发现了代码中的一个讨厌的错误: std::unique_lock<std::mutex> (some_mutex); 但这只是创建了一个临时对象。这使得RAII类型的大括号初始化实际上更加危险,因为它也可以在没有默认构造函数的类上工作: std::lock_guard<std::mutex> {some_mutex}; std::lock\u guard{some\u mutex}; 当然,这一切都归结为缺少一个标识符,但仍然可能导致极难找到错误。声明R

今天我无意中发现了代码中的一个讨厌的错误:

std::unique_lock<std::mutex> (some_mutex);
但这只是创建了一个临时对象。这使得RAII类型的大括号初始化实际上更加危险,因为它也可以在没有默认构造函数的类上工作:

std::lock_guard<std::mutex> {some_mutex};
std::lock\u guard{some\u mutex};
当然,这一切都归结为缺少一个标识符,但仍然可能导致极难找到错误。声明RAII类型的推荐方法是什么,以避免这种令人讨厌的情况

编辑:


我很清楚如何使用RAII类。要点是:如果您忘记了标识符,您可能永远不会注意到它,因为您通常不会再次使用该标识符。

您真正想要的是:

std::mutex some_mutex;
std::unique_lock<std::mutex> my_lock(some_mutex);
std::mutex some_mutex;
std::unique_lock my_lock(一些互斥锁);

我看不出有什么模棱两可的地方。对于RAII,匿名(临时)对象没有任何用处,因为它们会立即被销毁。因此,给它一个名称并传入互斥锁。

您真正想要的是:

std::mutex some_mutex;
std::unique_lock<std::mutex> my_lock(some_mutex);
std::mutex some_mutex;
std::unique_lock my_lock(一些互斥锁);

我看不出有什么模棱两可的地方。对于RAII,匿名(临时)对象没有任何用处,因为它们会立即被销毁。因此,给它一个名称并传入互斥锁。

我能建议的最好方法是使用带有pragma/属性“must use return”的函数。 这样
就可以使锁成为唯一的锁(我的互斥锁)
将生成一个警告,表明您没有使用返回的值,但是
auto locker=make_unique_lock(my_mutex)将根据需要工作。
但是,
if(make_unique_lock(my_mutex))
也将是合法的,并且可能会立即销毁临时文件。也许您可以通过删除
操作符bool()&&

然而,上次我查看时,unique_lock禁止所有复制/移动语义,因此不能以这种方式使用…
直到c++17,它允许返回值省略,即使在没有/删除复制和移动成员的情况下,那么这在c++17中是否可行

template <class Mutex>  [[nodiscard]]
std::unique_lock<Mutex> make_unique_lock(Mutex& m)
{
    return m;
}
模板[[nodiscard]]
std::unique_lock make_unique_lock(互斥锁&m)
{
返回m;
}
在C++11中,最好的方法可能是使用
auto&locker=make_unique_lock(myMutex)调用相同的方法
以避免被阻止的分配,但通过获取引用保持临时活动。当然,在c++11中,您必须使用vendor属性而不是[[nodiscard]]

注意,这种方法有利于模板arg的自动推导,因此实际上比传统的声明更简单

这都是半未经检验的说法


更重要的是:如果你可以用
[[nodiscard]]
来装饰构造函数,特别是在没有命名的情况下不能丢弃构造的对象,那么你就可以得到你想要的行为

我能建议的最好方法是使用pragma/attribute“must use return”的函数。 这样
就可以使锁成为唯一的锁(我的互斥锁)
将生成一个警告,表明您没有使用返回的值,但是
auto locker=make_unique_lock(my_mutex)将根据需要工作。
但是,
if(make_unique_lock(my_mutex))
也将是合法的,并且可能会立即销毁临时文件。也许您可以通过删除
操作符bool()&&

然而,上次我查看时,unique_lock禁止所有复制/移动语义,因此不能以这种方式使用…
直到c++17,它允许返回值省略,即使在没有/删除复制和移动成员的情况下,那么这在c++17中是否可行

template <class Mutex>  [[nodiscard]]
std::unique_lock<Mutex> make_unique_lock(Mutex& m)
{
    return m;
}
模板[[nodiscard]]
std::unique_lock make_unique_lock(互斥锁&m)
{
返回m;
}
在C++11中,最好的方法可能是使用
auto&locker=make_unique_lock(myMutex)调用相同的方法
以避免被阻止的分配,但通过获取引用保持临时活动。当然,在c++11中,您必须使用vendor属性而不是[[nodiscard]]

注意,这种方法有利于模板arg的自动推导,因此实际上比传统的声明更简单

这都是半未经检验的说法


更重要的是:如果你可以用
[[nodiscard]]
来装饰构造函数,特别是在没有命名的情况下不能丢弃构造的对象,那么你就可以得到你想要的行为

当然,这就是您应该如何使用这些RAII类型。但是您很容易忘记标识符,并且永远不会注意到,因为您不应该将其用于任何事情。在这种情况下,bug几乎没有被注意到,我知道没有更好的方法。C++并不是真正的保护用户免于自己的错误。我想您可以编写
auto my\u lock=std::unique\u lock(一些互斥锁)
(如果您“忘记”了
my\u lock
标识符,则会失败),但是。。。真的吗?通常RAII类型标识符非常短:
std::unique\u lock g(一些互斥体)
&
std::unique_lock(一些互斥锁)
我认为在这种情况下,它确实可以很容易地偶尔通过一次。您的解决方案无法处理具有已删除副本复制因子的类型。所以我想使用某种类型的静态分析器&小心是你能做的最好的事情“C++并不是真的在保护用户免受他们自己的错误的伤害”-我不同意-所有这些新型的共享ptr等等,都是为了给用户一种错误的安全感:-)当然,这就是你应该如何使用这些RAII类型。但是您很容易忘记标识符,并且永远不会注意到,因为您不应该将其用于任何事情。在这种情况下,bug几乎没有被注意到,我知道没有更好的方法。C++并不是真正的保护用户免于自己的错误。我想您可以编写
auto my\u lock=std::unique\u lock(一些互斥锁)
(如果您“忘记”了
my\u lock
I,就会失败)