我有以下代码:
class Foo;
class Bar;
class Bar {
public:
Bar() {
}
Bar(Foo &foo) {
}
};
class Foo {
public:
Foo() {
}
Foo(Foo &foo) {
}
Foo(const Bar &bar) {
}
};
Bar operator >> (const Bar &left, const Bar &right) { return Bar(); }
Foo a;
Foo b;
Foo c = a >> b;
在 Visual Studio 10 中,上述代码可以正常编译:编译器识别出 Bar
可以从 Foo&
实例化,因此它会调用适当的运算符 >>
,然后返回一个 Bar
实例,并适本地调用构造函数 Foo(const Bar &)
。
但是,GCC 4.5 不编译上述代码。它输出以下错误:
error: no matching function for call to 'Foo::Foo(Foo)'
note: candidates are: Foo::Foo(const Bar&)
note: Foo::Foo(Foo&)
note: Foo::Foo()
为什么会发生上述情况,根据语言标准,哪个编译器是正确的?
编辑:
为什么 C++ 由于 c = a >> b
而创建临时 Foo
对象,因为 Foo(const Bar &)
存在吗?
最佳答案
这与重载或参数查找无关。通过定义 Foo(Foo&)
,您已禁用默认复制构造函数 Foo(const Foo&)
的生成,该构造函数是初始化 c
所必需的> 来自右值。添加带有 Foo(const Foo&) 签名的 ctor,您的代码将运行良好。我不知道为什么 VS10 会编译这个,但我会尝试查找指定为什么它不应该发生的子句。
我们开始: §12.8(1) 指定类 X 的非模板构造函数是复制构造函数,如果其第一个参数的类型为 X&、const X&、 volatile X& 或 const volatile X& 并且没有其他参数或所有其他参数都有默认值。
§12.8(5) 说,如果我们没有为 X 定义复制构造函数(以上述任何形式),编译器将以 X(const X&) 的形式定义复制构造函数。
因此定义 Foo(Foo&) 定义了一个复制构造函数,因此编译器不能再隐式定义 Foo(const Foo&)。
关于c++ - 关于运算符重载和参数相关查找,Visual Studio 10 和 GCC 4.5 之间的哪个编译器是正确的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6358073/