IНеизвестная ссылка на указатель

Почему компилятор Visual Studio доволен

void fn(int *&i) 
{
    ;
}

а также

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

но нет

void fn(IUnkown *&p)
{
    ;
}

где это выглядит

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

ошибка компилятора

3 IntelliSense: ссылка типа "IUnknown *&" (без константы) не может быть инициализирована значением типа "IDXGIFactory *" c:\Users\Carl\Documents\Visual Studio 2013\Projects\Project1\Project5\main .cpp 29 10 Проект5

Самое близкое, что я обнаружил в ходе исследований, это то, что компилятор будет выполнять только одно преобразование типов за раз, но это не может быть правильным, потому что тогда const & version должен прервать выполнение преобразования типа и константы; однако именно версия & не будет компилироваться.


person Carl    schedule 23.10.2013    source источник


Ответы (1)


Неконстантная ссылка lvalue (например, IUnknown*&) может быть связана только с lvalue; он не может быть привязан к rvalue. Константная ссылка lvalue (например, 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, это lvalue.

В (1) мы инициализируем объект x (типа double) из i (типа int). Тип не совпадает, но это нормально, потому что происходит неявное преобразование из int в double. «Результатом» этого преобразования является выражение rvalue(*) типа double, которое используется для инициализации x.

В (2) мы инициализируем константную ссылку y (типа double const&) из i. Опять же, типы не совпадают, поэтому для преобразования int в double используется неявное преобразование. «Результатом» этого преобразования является rvalue. Как отмечалось в начале, ссылка с уточнением const может связываться с rvalue, поэтому y связывается с "результатом" преобразования.

В (3) мы пытаемся инициализировать неконстантную ссылку z (типа double&) из i. Типы не совпадают, поэтому потребуется преобразование. Преобразование здесь использовать нельзя, так как «результатом» преобразования является rvalue, а, как отмечалось в начале, неконстантная ссылка не может быть связана с rvalue. .

C++ имеет специальные правила, позволяющие привязывать ссылки const lvalue к выражениям rvalue. Вы можете узнать почему из других вопросов здесь, в StackOverflow, например "Почему неконстантная ссылка не может быть привязана к временному объекту?"

Ваш случай точно такой же, как и этот: тип вашего аргумента (IDXGIFactory*) не совпадает с типом параметра (IUnknown* или ссылка на него), поэтому требуется неявное преобразование для преобразования аргумента в тип параметра (в данном случае это преобразование указателя на производный класс в указатель на базовый класс). Однако «результатом» этого преобразования является выражение rvalue, поэтому оно не может привязываться к неконстантной ссылке IUnknown*&.


(*)Это действительно prvalue; Я использовал таксономию выражений С++ 98 в этом ответе для простоты. См. этот вопрос для получения информации о значении C++11. категории.

person James McNellis    schedule 23.10.2013
comment
the "result" of the conversion is an rvalue это то, чего мне не хватало. Благодарю вас! - person Carl; 25.10.2013