почему нет неявного преобразования из указателя в ссылку на указатель констант - PullRequest
9 голосов
/ 26 мая 2010

Я проиллюстрирую свой вопрос с помощью кода:

#include <iostream>

void PrintInt(const unsigned char*& ptr)
{
    int data = 0;
    ::memcpy(&data, ptr, sizeof(data));
    // advance the pointer reference.
    ptr += sizeof(data);
    std::cout << std::hex << data << " " << std::endl;
}

int main(int, char**)
{
    unsigned char buffer[] = { 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, };

    /* const */ unsigned char* ptr = buffer;

    PrintInt(ptr);  // error C2664: ...
    PrintInt(ptr);  // error C2664: ...    

    return 0;
}

Когда я запускаю этот код (в VS2008), я получаю следующее: ошибка C2664: «PrintInt»: невозможно преобразовать параметр 1 из «unsigned char *» в «const unsigned char * &». Если я раскомментирую комментарий "const", он будет работать нормально.

Однако не следует ли неявно преобразовать указатель в указатель на констант, а затем взять ссылку? Я ошибаюсь, ожидая, что это сработает? Спасибо!

Ответы [ 4 ]

11 голосов
/ 26 мая 2010

Если указатель преобразуется в константный указатель, как вы предлагаете, то результатом этого преобразования будет временное значение, rvalue . Вы не можете прикрепить неконстантную ссылку к rvalue - это недопустимо в C ++.

Например, этот код не будет компилироваться по аналогичной причине

int i = 42;
double &r = i;

Даже если тип int можно преобразовать в тип double, это еще не означает, что вы можете прикрепить ссылку double & к результату этого преобразования.

Однако константная ссылка (т. Е. Ссылка типа const на const) может быть присоединена к значению r, что означает, что этот код будет прекрасно компилироваться

int i = 42;
const double &r = i;

В вашем случае, если вы объявите свою функцию как

void PrintInt(const unsigned char* const& ptr) // note the extra `const`

код скомпилируется.

7 голосов
/ 26 мая 2010

Это нарушит правильность const:

// if it was allowed
const int x = 5;
int *p;
const int*& cp = p; // cp is a ´constant´ alias to p
cp = &x;            // make cp (and p) point to a constant
*p = 7;             // !!!!

Если преобразование было разрешено, приведенный выше код скомпилируется. Как только вы инициализировали cp с p (запрещено на языке), они стали псевдонимами. Теперь вы можете использовать cp для указания на любой постоянный объект, так как это указатель на константный объект. Изменение значения, на которое указывает p, также является допустимым кодом, поскольку это указатель на неконстантный объект, но поскольку p и cp одинаковы, это будет изменение константы.

0 голосов
/ 14 июня 2011

Невозможно преобразовать ссылку на указатель, поскольку указатель может быть нулевым, а ссылка - нет. Другими словами, ссылка является более строгой, чем указатель. Ссылка всегда является допустимым указателем, но обратное не всегда верно.

0 голосов
/ 26 мая 2010

Я думаю, вам нужно:

void PrintInt(const unsigned char* const& ptr)

если вы хотите передать константный указатель по ссылке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...