首先,这是“使用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);
}
答案 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.6
? 1
?从double
到int
的转换不是问题,但是您将如何找回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)
是无用的,因为交换发生在函数范围内,但不会在外部更改值。
另一个问题是您的函数期望参数类型为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
第二个错误是由于您将一个右值(临时值)传递给了一个需要左值的函数:
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不会执行任何操作。