Я не знаю разницы между этими кодами, когда я использую возврат по ссылке - PullRequest
1 голос
/ 11 октября 2019

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

Скажите, пожалуйста, почему и разницу двух кодов.

Код № 1:

#include <iostream>

using namespace std;

struct Pair {
    int first;
    int second;
};

Pair& swap(Pair&);

int main()
{
    Pair p1 = {10, 20};
    Pair p2 = swap(p1);
    return 0;
}

Pair& swap(Pair& pair)
{
    int temp;

    temp = pair.first;
    pair.first = pair.second;
    pair.second = temp;

    return pair;
}

Код № 2:

#include <iostream>

using namespace std;

struct Pair {
    int first;
    int second;
};

Pair& swap(int num1, int num2);

int main()
{
    Pair p = swap(10, 20);
    return 0;
}

Pair& swap(int num1, int num2)
{
    int temp;

    temp = num1;
    num1 = num2;
    num2 = temp;

    Pair pair = {num1, num2};
    return pair;
}

Ответы [ 3 ]

2 голосов
/ 11 октября 2019

Разница в том, что в коде № 1 функция main() объявляет переменную pair, поэтому она существует в области действия main(). В коде № 2 функция swap() объявляет переменную pair, поэтому она существует только в области действия функции swap(), и после выхода из функции подкачки переменная уничтожается.

1 голос
/ 11 октября 2019

Сначала вы можете избежать ненужного кода:

int temp = num1;
num1 = num2;
num2 = temp;

Pair pair = {num1, num2};

Зачем сначала менять номера, просто создайте пару с замененными числами:

Pair pair = {num2, num1};
//              ^     ^

Но теперь давайте рассмотрим различия(Я отбросил все детали, не относящиеся к проблеме, т.е. фактический обмен):

Pair& swap(Pair& pair)
{
    return pair;
}

В первом варианте вы получаете пару по ссылке. Эта пара должна быть создана снаружи и передана в функцию:

Pair p;  // created outside
swap(p); // swap uses reference to p outside
// p still exists
// swap returns just a reference to the same p it received
// -> you can use it for assignment:
Pair pp = swap(p);

Обратите внимание, что ваша функция поменяла местами исходный p, полученный по ссылке, поэтому оба p и pp содержат одинаковое содержимое. Таким образом, эти два фрагмента кода эквивалентны:

Pair p;
Pair pp = swap(p);

Pair p;
swap(p); // ignoring the return value
Pair pp = p;

Во втором варианте вы создаете пару внутри функции!

Pair& swap(int num1, int num2)
{
    Pair pair = {num1, num2};
    return pair;
}

Но время жизни парызаканчивается функцией выхода. Таким образом, вы возвращаете ссылку на пару, которая фактически уже была уничтожена, что приводит к неопределенному поведению .

Точно так же происходит, если вы принимаете пару по значению:

Pair& swap(Pair pair) // not a reference -> pair is copied into local variable
{
    return pair; // returning reference to local -> undefined behaviour!
}

Во всех случаях, когда вы хотите вернуть локальные переменные, вам нужно вернуть их по значению:

Pair swap(int, int)
{
    Pair pair;
    return pair; // return by value, value will be copied into target variable
                 // (actually, due to copy elision, directly written there)
}

Возвращение по значению также может быть полезно, если вы не хотите изменять парупередан функции (просто для полноты, это не значит, что нужно , чтобы изменить свою функцию на). Однако вы должны убедиться, что не измените переданную пару. Вы можете принять по константной ссылке и создать копию внутри;тем не менее, самый простой способ - это принимать по значению, что создает копию непосредственно при получении параметра:

Pair swap(Pair pair) // notice: both references dropped
{
    return pair;
};

Теперь p и pp do различаются (хорошо, если вы действительно реализовалиобмен, конечно):

Pair p;
Pair pp = swap(p);
0 голосов
/ 11 октября 2019

в # code2 пара существует только в области функции подкачки.

в # code1 вам нужна временная температура, потому что вы изменяете существующую пару и хотите сохранить значение, прежде чем изменить его. в # code2 (давайте проигнорируем основную проблему) вам нужно просто сформировать пару из полученного вами значения

    Pair& swap(int num1, int num2)
{
    Pair pair = {num1, num2};
    return pair;
}

, и если вы подумаете об этом, вы не поменяете местами пару, потому что у вас нет пары ..

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