通过不同类型的引用传递参数时如何进行类型转换

Posted

技术标签:

【中文标题】通过不同类型的引用传递参数时如何进行类型转换【英文标题】:How to typecast when passing argument by reference of different type 【发布时间】:2020-02-29 07:48:45 【问题描述】:

我不知道如何转换它。我尝试的一切总是失败。下面的代码显示了它

#include <iostream>

using namespace std;

void swaps(int &a, int &b)
    int temp; 
    temp = a, 
    a=b; 
    b=temp; 
    

int main()
    double dx = 7.7;    
    double dy = 9.9;

    //it's ok if dx is int
    //it's ok if dy is int

    swaps(int(dx),int(dy));                                  //#1
    swaps((int) dx,(int)dy);                                 //#2
    swaps(static_cast<int>(dx),static_cast<int>(dy));        //#3

    return 0;
    

所以,如果您能帮助我解决问题,我将非常感谢您。谢谢你:)

【问题讨论】:

这并没有解决问题,而是养成使用有意义的值初始化对象的习惯,而不是默认初始化它们并立即覆盖默认值。在这种情况下,这意味着将int temp; temp = a; 更改为int temp = a; 【参考方案1】:

问题

在这种情况下,类型转换会产生一个右值

见:Is it an Rvalue or Lvalue After a Cast

将这些右值传递给由非常量左值引用接收的函数会导致错误。

换句话说,您的类型转换变量不是您的原始变量。因此,交换这些类型转换的值是没有意义的。

您可以查看this 以了解 C++ 中的左值和右值。

解决方案

您可以阅读本文以了解有关您的问题的更多信息:

Error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’

但是,建议的解决方案不适用于您的 swap 函数,因为它必须通过非常量引用获取参数。但是类型转换产生的右值不允许你这样做。

如果您尝试通过右值引用获取参数,那么代码将编译,但不会交换您的原始变量,它只会交换那些临时右值。下面是一些代码来说明这一点:

#include <iostream>

using namespace std;

void swap(int&& a, int&& b) // rvalue reference (universal reference)

    cout << "Inside the swap function:-\n";
    cout << "a = " << a << '\n'; // 7
    cout << "b = " << b << '\n'; // 9

    int tmp;
    tmp = a;
    a = b;
    b = tmp;

    // You can process the swapped variables inside the function
    cout << "After Swapping:-\n";
    cout << "dx = " << a << '\n'; // 9
    cout << "dy = " << b << '\n'; // 7


int main()

    double dx = 7.7;
    double dy = 9.9;

    // Now this will compile       
    swap(static_cast<int>(dx), static_cast<int>(dy));

    // The function had swapped those temporary rvalues produced by the typecast
    // So you will not have the effect of swap outside the function
    cout << "Outside the swap function:-\n";
    cout << "dx = " << dx << '\n'; // 7.7
    cout << "dy = " << dy << '\n'; // 9.9
    return 0;

您可以查看this 以开始使用右值引用和移动语义。

更好的解决方案是使用 模板化 swap 函数,而不是在传递参数时依赖类型转换:

template <typename T>
void swap(T& a, T& b)

    T temp; 
    temp = a; 
    a = b; 
    b = temp; 

您可以在不转换原始变量的情况下调用此函数,并具有在函数内部和外部交换的效果。

如果你不知道模板是什么,那么你可以从here开始。

顺便说一句,C++ 有一个内置的交换函数std::swap。如您所见,即使这样也依赖于模板而不是类型转换来避免像您的情况那样的问题。

【讨论】:

感谢您的回答并帮助我,如果我可以列出两个答案我会做的,呵呵:) @WhoAmI 没问题。我添加了我的答案,因为现有答案建议您将参数作为 plain int 或再次使用 use cast,这两者都是不正确的,因为这不会帮助您交换你的原始变量。你试过了吗? 先生,上面答案中唯一的一项工作是直接更改变量类型,如您所说的类型转换只是返回右值,即不能引用文字 但是先生,您说的是什么意思:“如果您尝试通过右值引用获取参数,那么代码将编译,但不会交换您的原始变量,它只会交换那些临时右值。 "可以展示示例代码吗? 应该使用 std::swap 而不是自己编写模板交换(有一些陷阱)【参考方案2】:

简短的回答是函数swaps 的引用参数需要引用一些东西,称为“左值”。如果您更改了a 引用的值怎么办?会发生什么变化?

int(dx)(int)dxstatic_cast&lt;int&gt;(dx)的结果是“prvalues”(感谢@M.M的更正),不能通过引用传递。

要调用swaps,您需要更改它的签名以采用普通的int。或者将 dxdy 转换为 int 变量,然后传递这些变量。

有关详细信息,请参阅 this。

【讨论】:

感谢先生非常有帮助的回答:) 这三个表达式都是prvalues

以上是关于通过不同类型的引用传递参数时如何进行类型转换的主要内容,如果未能解决你的问题,请参考以下文章

swift基本语法——数据类型

Java基础——方法传值(基本数据类型 VS 引用数据类型)

值传递和引用传递(不是引用类型的传递)的区别

Java 中的传值与传引用

mybatis不同参数传递取值方式

mybatis不同参数传递取值方式