Disallowing creation of the temporary objects

后端 未结 8 930
南方客
南方客 2020-11-29 09:01

While debugging crash in a multithreaded application I finally located the problem in this statement:

CSingleLock(&m_criticalSection, TRUE);
8条回答
  •  再見小時候
    2020-11-29 09:39

    First, Earwicker makes some good points -- you can't prevent every accidental misuse of this construct.

    But for your specific case, this can in fact be avoided. That's because C++ does make one (strange) distinction regarding temporary objects: Free functions cannot take non-const references to temporary objects. So, in order to avoid locks that blip into and out of existence, just move the locking code out of the CSingleLock constructor and into a free function (which you can make a friend to avoid exposing internals as methods):

    class CSingleLock {
        friend void Lock(CSingleLock& lock) {
            // Perform the actual locking here.
        }
    };
    

    Unlocking is still performed in the destructor.

    To use:

    CSingleLock myLock(&m_criticalSection, TRUE);
    Lock(myLock);
    

    Yes, it's slightly more unwieldy to write. But now, the compiler will complain if you try:

    Lock(CSingleLock(&m_criticalSection, TRUE));   // Error! Caught at compile time.
    

    Because the non-const ref parameter of Lock() cannot bind to a temporary.

    Perhaps surprisingly, class methods can operate on temporaries -- that's why Lock() needs to be a free function. If you drop the friend specifier and the function parameter in the top snippet to make Lock() a method, then the compiler will happily allow you to write:

    CSingleLock(&m_criticalSection, TRUE).Lock();  // Yikes!
    

    MS COMPILER NOTE: MSVC++ versions up to Visual Studio .NET 2003 incorrectly allowed functions to bind to non-const references in versions prior to VC++ 2005. This behaviour has been fixed in VC++ 2005 and above.

提交回复
热议问题