Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Неявное преобразование типа со ссылкой на void*

Автор вопроса: LouenОтветов: 2

Я хочу написать функцию, которая изменяет заданный указатель любого типа; поэтому я объявил, что моя функция принимает void*&, полагаясь на неявное преобразование любого указателя в void*. Однако следующий код отказывается компилироваться, говоря, что он не может преобразовать int*в void*&.

void f(void*& x)
{
     x = 0;
}

int main() {

    int* a = new int;
    f(a);
    delete a;
    return 0;
}

Обратите внимание, что он отлично работает, если f объявлено принимающим int*& (но затем теряет свою универсальность) или если f объявлено принимающим void* (но тогда f может изменять свой аргумент только локально).

Таким образом, независимо работает правило неявного преобразования "любое T* в void*", правило неявного преобразования "T в T&" работает, но не оба одновременно? Почему это так? Что я здесь сделал не так?

(Я знаю, что мог бы использовать шаблонную функцию для f, это в основном из любопытства).

  • stackoverflow.com/ вопросов/399003/ нет гарантии, что sizeof(int *) == sizeof(double *) - поэтому нет способа сгенерировать код без шаблона, который делает то, что вы хотите. Karoly Horvath 07.10.2013
  • @KarolyHorvath: void* всегда достаточно большой, чтобы вместить указатель на любой объект. Также спорно, является ли возможная разница в размерах (кстати, нигде не замеченная в реальных реализациях) указателей объектов реальной и предполагаемой или просто придирчивой интерпретацией разбросанной стандартной формулировки. PlasmaHH 07.10.2013
  • @PlasmaHH: я не уверен, что вы намеревались передать этим ... должен ли код просто обнулить ячейку памяти для пустоты * (которая достаточно велика), потенциально перезаписав ячейку памяти другой переменной? Karoly Horvath 07.10.2013
  • @KarolyHorvath: помимо того, что он не компилируется (поскольку временные объекты не могут привязываться к неконстантным ссылкам), если бы это было законно, оно, скорее всего, делало бы задуманное, потому что возможная разница в размерах указателей объектов является чисто теоретической, как и предположения о возможном поведении недопустимой языковой конструкции. PlasmaHH 07.10.2013
  • Рассмотрим случай, когда вместо 0 в f вы написали new std::vector<int>. Вы понимаете, насколько безопасным было бы это преобразование? molbdnilo 07.10.2013
  • то, что вы называете чисто теоретическим, называется стандартом. Думаю, мы с самого начала прекрасно поняли друг друга, поэтому весь этот разговор бессмыслен. Karoly Horvath 07.10.2013

c++referenceimplicit-conversion

Ответы

Ответ 1 · рейтинг 2 · Some programmer dude

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

Конечно, это можно решить с помощью шаблонов:

template<typename T>
void f(T*& x) { ... }

Ответ 2 · PlasmaHH

Если бы это работало здесь, вы бы создали временный void* из T* (поскольку преобразование здесь действительно означает "создать новый объект другого типа"), к которому вы затем привязали бы ссылку, что не будет работать, так как это неконстант. Что будет работать, хотя:

void f(void* const & x)
{
     x = 0;
}

Но это, вероятно, не то, что вы имели в виду, поскольку речь идет о временном, а не о int*.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы