Nav*_*een 26 c++ mfc temporary
在多线程应用程序中调试崩溃时,我终于在此语句中找到了问题:
CSingleLock(&m_criticalSection, TRUE);
Run Code Online (Sandbox Code Playgroud)
请注意,它正在创建一个CSingleLock类的未命名对象,因此在此语句之后,临界区对象会立即解锁.这显然不是编码员想要的.此错误是由简单的输入错误引起的.我的问题是,有些我可以防止在编译时自己创建类的临时对象,即上面的代码类型应该生成编译器错误.一般来说,我认为每当一个类尝试进行某种资源获取时,就不应该允许该类的临时对象.有没有办法强制执行呢?
Dan*_*ker 14
编辑:正如j_random_hacker所说,可以强制用户声明一个命名对象以取出锁定.
然而,即使你的班级以某种方式禁止临时创建,用户也会犯类似的错误:
// take out a lock:
if (m_multiThreaded)
{
CSingleLock c(&m_criticalSection, TRUE);
}
// do other stuff, assuming lock is held
Run Code Online (Sandbox Code Playgroud)
最终,用户必须了解他们编写的一行代码的影响.在这种情况下,他们必须知道他们正在创建一个对象,他们必须知道它持续多长时间.
另一个可能的错误
CSingleLock *c = new CSingleLock(&m_criticalSection, TRUE);
// do other stuff, don't call delete on c...
Run Code Online (Sandbox Code Playgroud)
这会让你问"有什么方法可以阻止我的班级用户在堆上分配"吗?答案是一样的.
在C++ 0x中,通过使用lambdas,将有另一种方法来完成所有这些.定义一个功能:
template <class TLock, class TLockedOperation>
void WithLock(TLock *lock, const TLockedOperation &op)
{
CSingleLock c(lock, TRUE);
op();
}
Run Code Online (Sandbox Code Playgroud)
该函数捕获了CSingleLock的正确用法.现在让用户这样做:
WithLock(&m_criticalSection,
[&] {
// do stuff, lock is held in this context.
});
Run Code Online (Sandbox Code Playgroud)
这对用户来说更加困难.一开始语法看起来很奇怪,但是[&]后跟一个代码块意味着"定义一个不带args的函数,如果我按名称引用任何东西,它是外面的东西的名称(例如包含的局部变量)让我通过非const引用访问它,所以我可以修改它.)
首先,Earwicker提出了一些好处 - 你不能阻止每一次意外滥用这种结构.
但对于您的具体情况,实际上可以避免这种情况.那是因为C++确实对临时对象做了一个(奇怪的)区分:自由函数不能对非临时对象进行非const引用. 因此,为了避免突然进入和不存在的锁定,只需将锁定代码移出CSingleLock
构造函数并移动到自由函数中(您可以让朋友避免将内部暴露为方法):
class CSingleLock {
friend void Lock(CSingleLock& lock) {
// Perform the actual locking here.
}
};
Run Code Online (Sandbox Code Playgroud)
仍然在析构函数中执行解锁.
使用:
CSingleLock myLock(&m_criticalSection, TRUE);
Lock(myLock);
Run Code Online (Sandbox Code Playgroud)
是的,写起来稍微笨拙.但是现在,如果你尝试,编译器会抱怨:
Lock(CSingleLock(&m_criticalSection, TRUE)); // Error! Caught at compile time.
Run Code Online (Sandbox Code Playgroud)
因为非const ref参数Lock()
不能绑定到临时.
也许令人惊讶的是,类方法可以在临时工作 - 这就是为什么Lock()
需要成为一个自由函数.如果将friend
说明符和函数参数放在顶部代码段中以创建Lock()
方法,那么编译器将很乐意允许您编写:
CSingleLock(&m_criticalSection, TRUE).Lock(); // Yikes!
Run Code Online (Sandbox Code Playgroud)
MS编译器注意:直到Visual Studio .NET 2003的MSVC++版本错误地允许函数绑定到VC++ 2005之前的版本中的非const引用.此行为已在VC++ 2005及更高版本中 修复.
归档时间: |
|
查看次数: |
2419 次 |
最近记录: |