Двойной аргумент для параметра int и параметра int & - PullRequest
1 голос
/ 10 февраля 2020

Во-первых, это вопрос упражнения из книги «Программирование, принципы и практика с использованием C ++». В книгах специально было сказано, чтобы я написал эти функции, чтобы понять, почему некоторые строки вызывают проблемы. Поэтому изменение кода не вариант.

Я могу отправить двойные переменные или двойные литералы в качестве аргументов функции swap_v, которая использует передачу по значению (параметры типа).

Я не могу отправить двойные переменные или двойные литералы в качестве аргументов функции swap_r, которая использует передачу по ссылке (int & parameters). Это работает, когда я использую передачу по значению.

Обе строки дают эти 3 ошибки.

1 - ссылка типа "int &" (не квалифицированная как const) не может быть инициализирована значением типа "double"

2 - начальное значение ссылки на неконстантное должно быть lvalue

3- 'void swap_r (int &, int &)': невозможно преобразовать аргумент 1 из 'double' к 'int &'

#include <iostream>

void swap_v(int a, int b)
{
    int temp;
    temp = a;
    a = b;
    b = temp;
}

void swap_r(int& a, int& b)
{
    int temp;
    temp = a;
    a = b;
    b = temp;
}

int main()
{
    /*
    int x = 7;
    int y = 9;
    swap_v(x, y); // Doesnt swap
    swap_v(7, 9); // Cant swap literals.
    const int cx = 7;
    const int cy = 9;
    swap_v(cx, cy); // Doesnt swap
    swap_v(7.7, 9.9); // Cant swap literals.
    double dx = 7.7;
    double dy = 9.9;
    swap_v(dx, dy); // Doesnt swap
    swap_v(7.7, 9.9); // Cant swap literals.
    */

    int x = 7;
    int y = 9;
    swap_r(x, y); // Swaps
    // Doesnt compile. You have to pass variables when using pass by reference.
    //swap_r(7, 9);
    const int cx = 7;
    const int cy = 9;
    // Doesnt compile. You cant change constant values.
    //swap_r(cx, cy);
    // Doesnt compile. You have to pass variables when using pass by reference.
    //swap_r(7.7, 9.9);
    double dx = 7.7;
    double dy = 9.9;
    // ???
    swap_r(dx, dy);
    // ???
    swap_r(7.7, 9.9);
}

Ответы [ 4 ]

2 голосов
/ 10 февраля 2020

Вы можете получить int от double, но вы не можете получить int& от double.

В двух словах, здесь происходит следующее. Здесь:

void foo(int x) {}

double y = 5.0;
foo(y);

y - это не int, но double можно преобразовать в int, так что в основном у вас есть это (не совсем, но только для иллюстрации):

double y = 5.0;
int temp = y;
foo(temp);

Временный int передается в функцию. Теперь, если функция берет ссылку, вы не можете сделать

void bar(int& X) {}

bar(5);

, потому что вы не можете связать 5 с неконстантной ссылкой. Что бы это значило? Вы не можете изменить значение 5. Точно так же int, полученный в результате преобразования из double выше, является только временным, и передача его в качестве неконстантной ссылки не имеет смысла. Опять же, это не совсем то, что происходит, но это иллюстрирует «проблему»:

void bar(int& X) {}

double y = 5.0;
int temp = y;
bar(temp);

bar изменит temp, но это не повлияет на y. Поскольку это не совсем то, как работает преобразование (у вас нет int temp=y; явно в вашем коде), компилятор запрещает вам также делать

double y = 5.0;
bar(y);

PS Подумайте о том, как это сбивает с толку быть, если что-то подобное будет разрешено:

void half(int& x) { x /= 2; }

double x = 3.2;
half(x);

Что такое x сейчас? 1.6? 1? Преобразование из double в int не проблема, но как бы вы вернули double? Очевидно, что если допустить что-то подобное, это вызовет больше путаницы, чем поможет.

PPS swap - это не функция, которую вы должны написать. Вместо этого используйте std::swap.

1 голос
/ 10 февраля 2020

Эта строка:

swap_r(7.7, 9.9);

Невозможно скомпилировать, так как компилятор ожидает ссылку на переменную, и вы передаете ей литерал, это невозможно сделать. следовательно, ошибка:

начальное значение ссылки на non-const должно быть lvalue

Вы также не можете передать ссылку &double на &int Так как

swap_r(dx, dy);

передает double переменную ссылку на int ссылочный параметр, компиляция завершается ошибкой:

ссылка типа "int & "(не является константным) не может быть инициализирован значением типа" double "

void swap_r (int &, int &) ': невозможно преобразовать аргумент 1 из' double 'в' int &

0 голосов
/ 10 февраля 2020

Буква постоянна. Везде, где вы видите 3.1415, вы ожидаете, что оно будет иметь значение 3.1415, поэтому компилятор не позволит вам поменять его значение на что-то другое.

Смысл const в том, что вы называете значение, например, Pi - 3.1415. , Следовательно, cx и cy являются константами, а не переменными, поэтому их значения не могут изменяться.

Это не позволит вам вызывать swap_r с двойными значениями, потому что это не может быть сделано без введения счетного интуитивного поведения. Скажем, он преобразовал dx в int со значением 7, dy в int со значением 9, поменял их местами и преобразовал обратно в double. Вместо того, чтобы dx содержал 9.9 и dy содержал 7.7, они содержали бы 9 и 7. Это не то, что разумный человек мог бы ожидать от свопа.

Язык позволяет передавать двойные значения в swap_v путем их преобразования к временным постоянным целым числам. Эти константы могут быть переданы по значению в виде целых чисел, но не могут быть переданы по ссылке в качестве переменных, так как они исчезнут в конце оператора, что противоречит интуиции. Другими словами - вы не ожидаете, что swap ничего не сделает из-за того, что компилятор отбрасывает временные значения, созданные им из переменных.

0 голосов
/ 10 февраля 2020

Есть несколько проблем с вашим кодом. Прежде всего, функция void swap_v(int a, int b) бесполезна, так как подкачка происходит внутри области действия функции, но не меняет значений снаружи.

Другая проблема состоит в том, что ваши функции ожидают аргументы типа int или int&, но вы передаете double. Это скомпилирует, но усечет ваши значения, так как они преобразуются в int. Вы можете перегрузить функции или использовать шаблоны:

void swap_v(int a, int b) {...} // Gets called for ints
void swap_v(double a, double b) {...} // Gets called for doubles
template <typename T> void swap_v(T a, T b){...} // Works for all types

Вторая ошибка связана с тем, что вы передаете rvalue (временное значение) функции, которая ожидает lvalue:

void swap(int& a, int& b){...}
swap(7, 8);

Вам потребуется изменить сигнатуру функции на void swap(const int& a, const int& b), чтобы компилировать ее, но это не имеет никакого смысла, поскольку вы не можете использовать переданные значения вне вашей функции.

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

template <typename T>
void swap(T& a, T& b)
{
    T temp = std::move(a);
    a = std::move(b);
    b = std::move(temp);
}
...