尝试创建临时对象时出现奇怪的编译器错误

3
在我发表了这个问题之后,我尝试重现创建作用域RAII对象时发生意外rvalue创建的问题。现在看来,我无法在没有编译器错误的情况下重现它!
在以下代码示例中,在Test::foo()中,第二个ScopedLock创建不会编译。gcc编译器错误似乎完全错误。有人能解释一下吗?
struct Mutex
{
    void lock() { }

    void unlock() { }
};


struct ScopedLock
{
    ScopedLock(Mutex & inMutex) : mMutex(inMutex)
    { mMutex.lock(); }

    ~ScopedLock()
    { mMutex.unlock(); }

private:
    ScopedLock(const ScopedLock&);
    ScopedLock& operator=(const ScopedLock&);

    Mutex mMutex;
};


struct Test
{
    void foo()
    {
        // Compiles fine
        ScopedLock lock(mMutex);

        // Error: no matching function for
        // call to ‘ScopedLock::ScopedLock()’
        ScopedLock(mMutex);
    }

    Mutex mMutex;
};

我在Mac上使用GCC 4.2.1。

更新

我查看了原始代码,发现成员是通过this指针引用的:

ScopedLock(this->mMutex); // short-lived temporary and compiles fine

3
嘿,我在你之前的问题中就想到了这个......语法暗示这是一个函数调用,而不是临时对象。你可能希望问一下你的同事,他的情况是否比他表述的更加复杂一些。 - Shog9
是的,我明天一定会去查看它。 - StackedCrooked
@Shog9,事实证明他使用了以下语法:ScopedLock(this->mutex);。这个编译得很好。 - StackedCrooked
2个回答

5
你有两个用户声明的构造函数,因此没有编译器生成的默认构造函数。
是的,
Type (i);

与...处理方式相同

Type i;

这样的括号在更复杂的声明中非常有用,例如:
Type (*i)();

声明一个返回类型为函数指针的指针。

0
该消息告诉您,ScopedLock没有默认构造函数,即不带参数的构造函数。如果声明了带有参数的构造函数,C++ 将不会为您创建默认构造函数。

GCC是正确的,确实没有默认构造函数。然而,我调用的构造函数不是默认构造函数。它是一个带有Mutex&参数的构造函数。 - StackedCrooked
1
不,根据gcc的说法,您正在创建一个名为mMutex的ScopedLock。添加()构造函数,然后在调用ScopedLock(mMutex)之后调用mMutex.lock(),它会抱怨ScopedLock没有lock成员函数。 - Erik
@Erik,看来你是对的。GCC错了还是我的代码不合法? - StackedCrooked
没有仔细阅读标准,我认为GCC是正确的。MSVC给出了相应的错误信息。 - Erik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接