gpt4 book ai didi

C++ 推荐的 RAII 类型声明方式(unique_lock)

转载 作者:行者123 更新时间:2023-11-28 01:34:06 25 4
gpt4 key购买 nike

今天我在我们的代码中偶然发现了一个讨厌的错误:

std::unique_lock<std::mutex> (some_mutex);

注意缺少的标识符。我很惊讶这实际上编译并翻译成:

std::unique_lock<std::mutex> some_mutex;

它创建一个默认构造的 unique_lock,其名称与互斥量相同,这没问题,因为在这种情况下 some_mutex 在另一个范围内。事实证明,类型标识符可以简单地放在括号中,以便函数指针起作用。我认为这可以通过使用大括号初始化简单地解决:

std::unique_lock<std::mutex> {some_mutex};

但这只是创建了一个临时对象。这使得大括号初始化对于 RAII 类型实际上更加危险,因为它也适用于没有默认构造函数的类:

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

当然,这一切都归结为缺少标识符,但仍然可能导致极难发现错误。声明 RAII 类型以避免这种讨厌的极端情况的推荐方法是什么?

编辑:

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

最佳答案

我能建议的最好的方法是使用带有 pragma/attribute“必须使用 return”的函数。这样 make_unique_lock(my_mutex); 会生成一个警告,提示您没有使用返回值,但是 auto locker = make_unique_lock(my_mutex); 会按预期工作。
但是,if (make_unique_lock(my_mutex)) 也是合法的,并且可能会立即销毁临时文件。也许您可以通过删除 operator bool()&&

来阻止它

但是,我上次看,unique_lock 禁止了所有复制/移动语义,所以不能这样使用...
直到 c++17,即使在复制和移动成员不存在/删除的情况下也允许返回值省略,所以也许这在 c++17 中有效?

template <class Mutex>  [[nodiscard]]
std::unique_lock<Mutex> make_unique_lock(Mutex& m)
{
return m;
}

在 C++11 中,你能做的最好的事情可能是用 auto& locker = make_unique_lock(myMutex); 调用相同的方法来避免被阻塞的分配,但通过采取引用。当然,在 C++11 中,您必须使用供应商属性而不是 [[nodiscard]]。

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

这都是半未经测试的谈话。

更重要的是:如果你可以用 [[nodiscard]] 装饰构造函数,并具有你不能丢弃构造的特殊含义对象而不命名它,那么你就会得到你想要的行为!

关于C++ 推荐的 RAII 类型声明方式(unique_lock),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50121351/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com