int 参数和 int& 参数的双参数

Double argument to int parameter and int& parameter

首先,这是《Programming, Principles and Practice Using C++》一书中的一道练习题。书上有意让我写这些函数来理解为什么有些行会出问题。所以更改代码不是一个选项。

我能够将双精度变量或双精度文字作为参数发送给使用按值传递(int 参数)的 swap_v 函数。

我无法将双精度变量或双精度文字作为参数发送给使用引用传递(int& 参数)的 swap_r 函数。当我使用按值传递时它有效。

这两行都给出了这 3 个错误。

1- 类型“int &”(非 const 限定)的引用不能用类型“double”的值初始化

2- 非常量引用的初始值必须是左值

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);
}

这一行:

swap_r(7.7, 9.9);

无法编译,因为编译器需要变量引用,而您将其传递给文字,这是无法完成的。因此错误:

initial value of reference to non-const must be an lvalue

您也不能将 &double 引用传递给 &int 引用,所以因为

swap_r(dx, dy);

double 变量引用传递给 int 引用参数,编译失败并出现错误:

a reference of type "int &" (not const-qualified) cannot be initialized with a value of type "double"

void swap_r(int &,int &)': cannot convert argument 1 from 'double' to 'int &

您可以从 double 获得 int,但不能从 double.

获得 int&

简而言之,这里发生的事情如下:

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 的值。同样,从上面的 double 转换而来的 int 只是暂时的,将其作为非常量引用传递是没有意义的。同样,这并不是真正发生的事情,但它说明了“问题”:

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.61?从 doubleint 的转换不是问题,但是您如何取回 double?显然,如果允许这样的事情,它会造成更多的混乱而不是帮助。

PPS swap 不是您应该编写的函数。请改用 std::swap

您的代码有几个问题。首先,函数 void swap_v(int a, int b) 是无用的,因为交换发生在函数范围内,但不会改变外部的值。

另一个问题是您的函数需要 intint& 类型的参数,但您传递了 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

第二个错误来自于您将右值(临时值)传递给需要左值的函数:

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);
}

文字是常量。无论您在哪里看到 3.1415,您都希望它的值为 3.1415,因此编译器不允许您将其值与其他值交换。

const的意思就是给一个值命名,例如圆周率为 3.1415。因此,cx 和 cy 是常量,不是变量,所以它们的值不能变化。

它不允许您用双打调用 swap_r,因为如果不引入违反直觉的行为,它就无法这样做。假设它将 dx 转换为值为 7 的 int,将 dy 转换为值为 9 的 int,交换它们,然后将它们转换回双精度值。而不是让 dx 包含 9.9 和 dy 包含 7.7,它们将包含 9 和 7,这不是一个合理的人期望 swap 做的事情。

该语言确实允许通过将双精度数转换为临时常量整数来将它们传递给 swap_v。这些常量可以作为整数按值传递,但不能作为变量按引用传递,因为它们会在语句结束时消失,这是违反直觉的。换句话说 - 你不希望 swap 什么都不做,因为编译器会丢弃它从变量创建的临时值。