Есть ли разница или предпочтение между ptr ** и ptr * & в C ++ при вызове функций? - PullRequest
0 голосов
/ 29 августа 2018

Есть ли разница или предпочтительный способ изменения указателя в функции? Возьмите этот фрагмент, например,

    void change(int** ptr) {
        **ptr = 50;
        *ptr = nullptr;
    }

    void change(int*& ptr) {
        *ptr = 50;
        ptr = nullptr;
    }

    int main()
    {
        int a = 5;

        int* ptr = &a;
        int** ptr2 = &ptr;

        std::cout << "value: " << a << std::endl;
        std::cout << "value: " << ptr << std::endl;
        std::cout << "value: " << ptr2 << std::endl;

        change(ptr2);
        //change(ptr);

        std::cout << "value: " << a << std::endl;
        std::cout << "value: " << ptr << std::endl;
        std::cout << "value: " << ptr2 << std::endl;


        system("pause");

    }

Кажется, что обе функции изменения могут достичь того, что я спрашиваю, но я не уверен в разнице, кроме того, что функция ссылки не создает копию указателя?

Ответы [ 3 ]

0 голосов
/ 29 августа 2018

Вы можете иметь нулевой указатель, но не нулевую ссылку.

Вы можете предоставить первое с nullptr, и оно скомпилирует 1 , потому что существует неявное преобразование из std::nullptr_t в int**. Если вы попытались предоставить второму значение nullptr, произойдет сбой. Лучшим совпадением будет преобразование std::nullptr_t в int*, но вы не можете связать изменяемую ссылку с временным.

Я рассматриваю различные ситуации для различных способов передачи параметров в этом ответе , который также включает соображения владения объектом (с std::unique_ptr)

1. Поведение будет неопределенным, потому что вы разыменовываете его.

0 голосов
/ 29 августа 2018

Есть ли разница ... между ptr ** и ptr * & ...

Да. Первый является указателем на объект типа ptr*, а второй - ссылкой на объект типа ptr*.

или предпочтительнее ...

void change(int** ptr) {
    **ptr = 50;
    *ptr = nullptr;
}

void change(int*& ptr) {
    *ptr = 50;
    ptr = nullptr;
}

Преимущества справки

Вы обнаружите, что ссылка неявно перенаправлена, что упрощает синтаксис и обычно способствует удобочитаемости. Это особенно важно в случае ссылки / указателя на указатель. То же самое относится и к получению справки: вам не нужно использовать оператор адреса.

Другое преимущество состоит в том, что ссылка не может быть переназначена для ссылки на другой объект. Это упрощает чтение программ, использующих ссылки, поскольку вам не нужно выяснять, переназначена ли ссылка в длинном алгоритме; Вы знаете, что это не так.

Еще одним преимуществом является то, что ссылка не может быть нулевой. Поэтому вам не нужно проверять такую ​​возможность внутри функции. Если вы передадите null в первую примерную функцию, поведение будет неопределенным, что очень плохо.

Недостатки справки

Вы обнаружите, что ссылка неявно перенаправлена. Это может сбивать с толку людей, знакомых только с типами значений (программисты на Си).

Другим недостатком является то, что ссылка не может быть переназначена для ссылки на другой объект. Похоже, что это не проблема для вашей функции, так как вам не нужно ссылаться на более чем один объект, но в целом есть ситуации, когда это будет полезно.

Другим недостатком является то, что ссылка не может быть нулевой. Похоже, что это не проблема для вашей функции, которая, по-видимому, никогда не предназначена для обработки такого случая. Но в целом, существуют ситуации, когда вы хотите представить ссылочное отношение к несуществующему объекту.


Предпочтения являются личными, но, на мой взгляд, преимущества ссылки перевешивают недостатки, за исключением тех случаев, когда вам нужна одна из невозможных функций (обнуляемость, переназначение)

0 голосов
/ 29 августа 2018

Это во многом вопрос личного вкуса.

Тем не менее, при вызове void change(int** ptr), поскольку вы склонны передавать адрес чего-либо с помощью &, на вызывающем сайте более понятно, что «что-то» может быть изменено функция. Если вы используете перегрузку int*& ptr, это не так ясно, поскольку синтаксис вызова идентичен для передачи по значению и передачи по ссылке.

Помимо вышесказанного, я склонен использовать указатели в качестве параметров функции, если разрешено nullptr, и ссылки, если нет.

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