在多线程应用程序中调试崩溃时,我终于在以下语句中找到了问题:
CSingleLock(&m_criticalSection, TRUE);
请注意,它正在创建一个未命名的 CSingleLock 类对象,因此临界区对象在此语句之后立即解锁。这显然不是程序员想要的。这个错误是由一个简单的打字错误引起的。我的问题是,有没有办法可以防止在编译时创建一个类的临时对象,即上述类型的代码应该产生编译器错误。一般来说,我认为每当一个类试图进行某种资源获取时,就不应该允许该类的临时对象。有没有办法强制执行?
最佳答案
编辑:正如 j_random_hacker 所说,可以强制用户声明一个命名对象以获取锁。
但是,即使您的类(class)以某种方式禁止创建临时对象,用户也可能会犯类似的错误:
// take out a lock:
if (m_multiThreaded)
{
CSingleLock c(&m_criticalSection, TRUE);
}
// do other stuff, assuming lock is held
最终,用户必须了解他们编写的一行代码的影响。在这种情况下,他们必须知道他们正在创建一个对象,并且他们必须知道它会持续多久。
另一个可能的错误:
CSingleLock *c = new CSingleLock(&m_criticalSection, TRUE);
// do other stuff, don't call delete on c...
这会导致您问“有什么方法可以阻止我的类的用户在堆上分配它”?答案是一样的。
在 C++0x 中,将有另一种方法来完成这一切,即使用 lambda。定义一个函数:
template <class TLock, class TLockedOperation>
void WithLock(TLock *lock, const TLockedOperation &op)
{
CSingleLock c(lock, TRUE);
op();
}
该函数捕获了 CSingleLock 的正确用法。现在让用户这样做:
WithLock(&m_criticalSection,
[&] {
// do stuff, lock is held in this context.
});
这对用户来说更难搞砸。语法起初看起来很奇怪,但 [&] 后跟一个代码块意味着“定义一个不带参数的函数,如果我按名称引用任何东西,它是外部某物的名称(例如,包含函数)让我通过非常量引用访问它,所以我可以修改它。)
关于c++ - 不允许创建临时对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/914861/