0

为什么 Visual Studio 编译器对

void fn(int *&i) 
{
    ;
}

void fn(IUnknown *const &p)
{
    ;
}

但不是

void fn(IUnkown *&p)
{
    ;
}

在哪里调用它看起来像

IDXGIFactory *df = nullptr;
// init df
fn(df);

编译器错误是

3 IntelliSense:不能使用“IDXGIFactory *”类型的值初始化“IUnknown *&”类型的引用(非 const 限定)c:\Users\Carl\Documents\Visual Studio 2013\Projects\Project1\Project5\main .cpp 29 10 项目5

我在研究中发现的最接近的事情是编译器一次只会进行一次类型转换,但这不可能是正确的,因为这样const & 版本应该会中断进行类型和 const 转换;但是实际上无法编译的是 & 版本。

4

1 回答 1

2

非 const 左值引用(如IUnknown*&)只能绑定到左值;它不能绑定到rvalue。一个 const 限定的左值引用(如IUnknown* const&可以绑定到一个右值

考虑一个不涉及指针或函数调用的更简单的情况会更容易:

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(类型)对象。类型不匹配,但这没关系,因为存在从to的隐式转换。此转换的“结果”是一个类型为 的右值表达式(*),用于初始化。doubleiintintdoubledoublex

(2)中,我们从 初始化 const 限定引用y(类型为double const&i。同样,类型不匹配,因此使用隐式转换将 to 转换intdouble。这种转换的“结果”是一个rvalue。如开头所述,一个 const 限定的引用可以绑定到一个rvalue,因此y绑定到转换的“结果”。

(3)中,我们尝试从 初始化非常量引用z(类型为double&i。类型不匹配,因此需要进行转换。此处不能使用转换,因为转换的“结果”是rvalue,并且如开头所述,非常量引用不能绑定到rvalue

C++ 有特殊规则允许 const 左值引用绑定到右值表达式。您可以从 StackOverflow 上的其他问题中找出原因,例如“为什么非常量引用不能绑定到临时对象?”

您的情况与此情况完全相同:您的参数(IDXGIFactory*)的类型与参数的类型(IUnknown*或对其的引用)不同,因此需要隐式转换才能将参数转换为参数类型(在在这种情况下,它是从指向派生类的指针到指向基类的指针的转换)。然而,这种转换的“结果”是一个右值表达式,因此它不能绑定到非常量引用IUnknown*&


(*)这真的是一个prvalue;为简单起见,我在此答案中使用了 C++98 表达式分类法。有关 C++11 值类别的信息,请参阅此问题

于 2013-10-23T21:10:59.877 回答