如何避免C++匿名对象

Ray*_*ond 14 c++ g++

我有一个ScopedLock类可以帮助在超出范围时自动释放锁定.但问题是:有时团队成员会编写无效的锁码,例如

{
    ScopedLock(mutex);   // anonymous
    xxx;
}
Run Code Online (Sandbox Code Playgroud)

上面的代码是错误的,因为ScopedLock对象是立即构造和销毁的,因此无法锁定预期的区域(xxx).我希望编译器在尝试编译此类代码时出错.可以这样做吗?

我搜索了g++警告选项,但找不到合适的警告选项.

Seb*_*edl 8

我在一个代码库中看到了一个有趣的技巧,但它只有在你的scoped_lock类型不是模板时才有效(std :: scoped_lock是).

#define scoped_lock(x) static_assert(false, "you forgot the variable name")
Run Code Online (Sandbox Code Playgroud)

如果您正确使用该类,则可以

scoped_lock lock(mutex);
Run Code Online (Sandbox Code Playgroud)

并且由于scoped_lock标识符后面没有打开的paren,宏不会触发,代码将保持原样.如果你写

scoped_lock(mutex);
Run Code Online (Sandbox Code Playgroud)

宏将触发,代码将被替换

static_assert(false, "you forgot the variable name");
Run Code Online (Sandbox Code Playgroud)

这将生成信息性消息.

如果您使用限定名称

threads::scoped_lock(mutext);
Run Code Online (Sandbox Code Playgroud)

然后结果仍然无法编译,但消息不会那么好.

当然,如果您的锁是模板,那么错误的代码就是

scoped_lock<mutex_type>(mutex);
Run Code Online (Sandbox Code Playgroud)

这不会触发宏.


Lig*_*ica 5

不,不幸的,正如我去年在一篇博客文章中探讨的那样,没有办法做到这一点.

在其中,我得出结论:

我想故事的寓意是在使用s 时要记住这个故事scoped_lock.


您可以尝试强制团队中的所有程序员使用宏或范围换技巧,但如果您可以保证在每种情况下都可以保证在每种情况下都能捕获此错误.

您正在寻找一种以编程方式捕获此特定错误的方法,并且没有.


lee*_*mes 2

为了避免这种情况,请引入一个宏来为您执行此操作,并且始终对储物柜使用相同的名称:

#define LOCK(mutex) ScopedLock _lock(mutex)
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它:

{
    LOCK(mutex);
    xxx;
}
Run Code Online (Sandbox Code Playgroud)

作为替代方案,synchronize可以使用宏构造来模拟 Java 的块:在始终运行一次的 for 循环中,我在 for 循环的初始化语句中实例化这样的锁,因此在离开 for 循环时它会被销毁。

然而,它也有一些缺陷,break语句的意外行为就是一个例子。这里就介绍一下这个“hack” 。


当然,上述方法都不能完全避免像您​​的示例那样的意外代码。但如果您习惯使用这两个宏之一编写锁定互斥体,则这种情况发生的可能性较小。由于locker类的名称将永远不会出现在除了宏定义之外的代码中,您甚至可以在版本控制系统中引入提交钩子以避免提交无效代码。