C++代码中的额外括号括号

bob*_*obo 13 c++ curly-braces

有时你遇到的代码有额外的括号括号,与范围无关,只是为了便于阅读和避免错误.

例如:

GetMutexLock( handle ) ; 
{
  // brace brackets "scope" the lock,
  // must close block / remember
  // to release the handle.
  // similar to C#'s lock construct
}
ReleaseMutexLock( handle ) ;
Run Code Online (Sandbox Code Playgroud)

我见过的其他地方是:

glBegin( GL_TRIANGLES ) ;
{
  glVertex3d( .. ) ;
  glVertex3d( .. ) ;
  glVertex3d( .. ) ;
} // must remember to glEnd!
glEnd() ; 
Run Code Online (Sandbox Code Playgroud)

如果未释放互斥锁,则会引入编译器错误(假设您同时记住}和Release()调用).

  1. 这是一种不好的做法吗?为什么?
  2. 如果它不是一个,它可以改变代码编译的方式或使其变慢吗?

GMa*_*ckG 32

大括号本身很好,他们所做的只是限制范围,你不会放慢速度.它可以被视为更清洁.(总是喜欢干净的代码而不是快速的代码,如果它更干净,在配置之前不要担心速度.)


但是就资源而言,这是不好的做法,因为你已经让自己处于泄漏资源的位置.如果块中的任何东西抛出或返回,那么你已经死了.

使用范围绑定资源管理(SBRM,也称为RAII),通过使用析构函数将资源限制为范围:

class mutex_lock
{
public:
    mutex_lock(HANDLE pHandle) :
    mHandle(pHandle)
    {
        //acquire resource
        GetMutexLock(mHandle);
    }

    ~mutex_lock()
    {
        // release resource, bound to scope
        ReleaseMutexLock(mHandle);
    }

private:
    // resource
    HANDLE mHandle;

    // noncopyable
    mutex_lock(const mutex_lock&);
    mutex_lock& operator=(const mutex_lock&);
};
Run Code Online (Sandbox Code Playgroud)

所以你得到:

{
  mutex_lock m(handle);
  // brace brackets "scope" the lock,
  // AUTOMATICALLY
}
Run Code Online (Sandbox Code Playgroud)

这将是所有资源,它更清洁,更安全.如果你能够说"我需要释放这个资源",你就做错了; 他们应该自动处理.

  • + 1正确性...这个新的SBRM首字母缩略词我不知道!就表达意图而言,比RAII好多了.甚至似乎没有维基百科页面! (7认同)

Zan*_*ynx 17

大括号影响变量范围.据我所知,这就是他们所做的一切.

是的,这会影响程序的编译方式.将在块的末尾调用析构函数,而不是等到函数结束.

这通常是你想要做的.例如,您的GetMutexLock和ReleaseMutexLock将是更好的C++代码,如下所示:

struct MutexLocker {
  Handle handle;
  MutexLocker(handle) : handle(handle) { GetMutexLock(handle); }
  ~MutexLocker() { ReleaseMutexLock(handle); }    
};
...
{
  MutexLocker lock(handle);
  // brace brackets "scope" the lock,
  // must close block / remember
  // to release the handle.
  // similar to C#'s lock construct
}
Run Code Online (Sandbox Code Playgroud)

使用这种更多的C++样式,锁定会在块结束时自动释放.它将在所有情况下释放,包括异常,但setjmp/longjmp或程序崩溃或中止除外.

  • 您需要为储物柜命名,或者它只是一个临时死亡的储物柜.您应该更改后面的注释以匹配新的资源管理. (12认同)
  • @KennyTM不是它`MutexLocker锁(句柄);`? (3认同)