为什么Visual Studio编译器满意
void fn(int *&i)
{
;
}
和
void fn(IUnknown *const &p)
{
;
}
但不是
void fn(IUnkown *&p)
{
;
}
调用它看起来像
IDXGIFactory *df = nullptr;
// init df
fn(df);
编译错误是
3智能感知:类型为“IUnknown *&”的参考(不是const限定)无法使用“IDXGIFactory *”类型的值初始化c:\ Users \ Carl \ Documents \ Visual Studio 2013 \ Projects \ Project1 \ Project5 \ main.cpp 29 10 Project5
我用研究得出的最接近的事情是编译器一次只会进行一次类型转换,但这不可能是正确的,因为那时 const&版本应该从进行类型和const转换中断;但是& 版本实际上无法编译。
答案 0 :(得分:2)
非const左值引用(如IUnknown*&
)只能绑定到左值;它无法绑定到 rvalue 。 const限定的左值引用(如IUnknown* const&
)可以绑定到 rvalue 。
更容易考虑一个不涉及指针或函数调用的简单案例:
int i = 0;
double x = i; // (1) Well-formed
double const& y = i; // (2) Well-formed
double& z = i; // (3) Ill-formed
此处,i
是int
类型的对象。在表达式中使用i
时,它是左值。
在(1)中,我们从x
(类型double
)初始化对象i
(int
类型)。类型不匹配,但这没关系,因为存在从int
到double
的隐式转换。此转换的“结果”是类型为double
的 rvalue 表达式(*),用于初始化x
。
在(2)中,我们从y
初始化const限定引用double const&
(类型i
)。同样,类型不匹配,因此隐式转换用于将int
转换为double
。此转化的“结果”是 rvalue 。如开头所述,const限定引用可以绑定到 rvalue ,因此y
绑定到转换的“结果”。
在(3)中,我们尝试从z
初始化非const引用double&
(类型i
)。类型不匹配,因此需要进行转换。此处无法使用转换,因为转换的“结果”是 rvalue ,并且如开头所述,非const引用无法绑定到 rvalue
C ++有一些特殊规则允许const左值引用绑定到 rvalue 表达式。您可以在StackOverflow上找到其他问题的原因,例如"How come a non-const reference cannot bind to a temporary object?"
您的情况与此情况完全相同:您的参数类型(IDXGIFactory*
)与参数类型(IUnknown*
或其引用)不同,因此隐含转换是将参数转换为参数类型所需的转换(在这种情况下,它是从指向派生类的指针转换为指向基类的指针)。但是,此转换的“结果”是rvalue表达式,因此它无法绑定到非const引用IUnknown*&
。
(*)这真的是一个价值;为简单起见,我在这个答案中使用了C ++ 98表达式分类法。有关C ++ 11值类别的信息,请参阅this question。