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

时间:2020-02-10 09:59:50

标签: c++ pass-by-reference pass-by-value

首先,这是“使用C ++编程,原理和实践”一书中的一个练习题。这些书故意告诉我编写这些功能,以了解为什么某些行会引起问题。因此,更改代码不是一种选择。

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

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

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

1-无法使用类型为“ double”的值初始化类型为“ int&”的引用(非const限定)

2-引用非const的初始值必须为左值

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 个答案:

答案 0 :(得分:2)

您可以从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.61?从doubleint的转换不是问题,但是您将如何找回double?显然,如果允许这样的事情,将会引起更多的混乱。

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

答案 1 :(得分:1)

此行:

swap_r(7.7, 9.9);

由于编译器期望变量引用,并且您将其传递为文字,因此无法编译,因此无法完成。因此出现错误:

引用非常量的初始值必须为左值

您也不能传递对&double引用的&int引用,因此自

swap_r(dx, dy);

正在将double变量引用传递给int引用参数,编译失败并显示以下错误:

类型为“ int&”(不是const限定)的引用不能使用类型为“ double”的值初始化

void swap_r(int&,int&)':无法将参数1从'double'转换为'int&

答案 2 :(得分:1)

您的代码有几个问题。首先,函数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 :(得分:1)

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

const的含义是您命名一个值,例如Pi升至3.1415。因此,cx和cy是常量,而不是变量,因此它们的值不会改变。

它不允许您使用double调用swap_r,因为在不引入反直观行为的情况下将无法进行调用。假设将dx转换为值为7的int,将dy转换为值为9的int,将它们交换,然后将其转换为double。而不是dx包含9.9和dy包含7.7,它们将包含9和7,这不是一个合理的人期望交换执行的操作。

该语言确实允许将双精度数传递给swap_v,方法是将它们转换为临时常量int。这些常量可以作为整数通过值传递,但不能作为变量通过引用传递,因为它们会在语句末尾消失,这很直观。换句话说,由于编译器会丢弃它从变量创建的临时值,因此您不希望swap不会执行任何操作。