是否有可能以任何方式(静态分析)阻止或检测以下错误,其中堆栈分配的对象未被捕获并超出其构造的同一行的范围?
Resource resourceA, resourceB;
void someFunction()
{
ScopedResourceBinder resourceBindA( resourceA );
ScopedResourceBinder( resourceB ); // <--- BUG
}
第一个ScopedResourceBinder
是正确的,但第二个没有做任何事情,因为它在“绑定”之后立即“解除绑定”(假设说)。
这显然是一个程序员错误,但我现在已经调试了几次(几个小时的几个小时)并且很难发现。一旦你看到它,你会认为“这是一个愚蠢的啊”,但在实践中,很容易犯错误,编译器无法控制......或者是它?
背景信息:我使用的是一个大量使用RAII类来推送弹出状态的库,例如OpenGL资源。使用范围管理绑定是手动调用bind()/ unbind()函数的一个重大改进,但是这里列出的潜在错误会出现这种新模式。
答案 0 :(得分:2)
ScopedResourceBinder( resourceB );
与ScopedResourceBinder resourceB;
相同,即它声明一个名为resourceB
的命名变量,调用ScopedResourceBinder
的默认构造函数。
这一直持续到函数结束,但它仍然是一个bug,因为它没有执行绑定到变量resourceB
的意图。
为防止出现这种特殊情况,您可以确保ScopedResourceBinder
没有默认构造函数。
答案 1 :(得分:0)
在一般的编码实践中,我们应该在类定义本身中明确表达我们的意图。
例如:
如果我们想要单例类,那么所有构造函数都应该是私有的。
如果我们想用一些变量构造一个对象,那么只有所需的构造函数应该公开公开,所有应该被称为私有。
通过这种方式,我们只能在编译时标记所有错误的用法。