【问题标题】:Passing by reference in C++ function在 C++ 函数中通过引用传递
【发布时间】:2020-02-16 12:41:35
【问题描述】:

我正在编写一个简单的程序来使用函数计算 6^5。这是我的代码

#include <iostream>
using namespace std;

int raiseToPower(int &base, int exponent){
 for (int i = 1; i < exponent; i = i + 1){
   base= base * base;
   }
 return base;
}

int main() {
 int base = 6;
 cout << "6^5 is " << raiseToPower(base, 5)<< endl;

 return 0;
}

结果是

 6^5 is -683606016

而不是 7776

你们能解释一下为什么我得到这个结果吗? 我不是在寻找另一种编写此代码的方法。我知道有更简单的方法,但我试图了解出了什么问题

【问题讨论】:

  • 你不是在计算base^exponent,你是在计算base^(2^(exponent-1))。
  • 您的计算量比6^5 大得多。 base = base*base;这是按指数的 2 次幂计算的
  • 您的第一次迭代执行base = 6 * 6,即36,并将其分配给base。所以下一次迭代是36 * 36,也就是1296,然后你再次将它分配给base,...
  • 在这里传递base 作为参考并没有什么意义。您期望从中获得什么好处?
  • @t.niese 不建议将 std::pow 用于整数。至少不是不提这整罐蠕虫:stackoverflow.com/questions/9704195/why-pow10-5-9-999-in-c

标签: c++ function loops for-loop definition


【解决方案1】:

为什么要使用引用传递。设置尽可能多的const 可以减少出错的几率:

#include <iostream>
using namespace std;

int raiseToPower(const int base, const int exponent) {
    int result = base;
    for (int i = 1; i < exponent; i = i + 1){
        result = result * base;
    }
    return result;
}

int main() {
    int base = 6;
    cout << "6^5 is " << raiseToPower(base, 5)<< endl;

    return 0;
}

如果它必须是通过引用传递,你可以这样做:

#include <iostream>
using namespace std;

void raiseToPower(const int base,
                 const int exponent,
                 int &result)
{
    result = base;
    for (int i = 1; i < exponent; i = i + 1){
        result = result * base;
    }
}

int main() {
    int base = 6;
    int result;
    raiseToPower(base, 5, result);

    cout << "6^5 is " << result << endl;

    return 0;
}

【讨论】:

  • 它们不是多余的。它们可以防止您意外更改您从未打算更改的值。它们从字面上改变了代码是否可以编译。这就是冗余的对立面的定义。
  • 它会阻止您更改函数内部中您不想更改的值。
  • 我们说的不是函数的用户,而是函数的实现者。
  • 我的意思是公平的用户。它们对函数接口并不重要,但我个人认为它们使实现阅读起来稍微快一些,我确切地知道我在看哪里,而不必考虑函数的其余部分做了什么。
  • @VladfromMoscow,我不知道你在这里没有得到什么,但让我最后一次说一下,我不是在谈论函数的接口,或者它的签名,或者是否或不包含在签名中的按值传递参数的常量。我什至不是在谈论函数参数——我在谈论任何旧变量,甚至是局部函数变量。将它们设为 const 可防止您以后意外更改它们。如果您尝试这样做,您将收到编译时错误。就是这样。你说这不是真的吗?
【解决方案2】:

您的计算不正确。可变基数的值不应改变。试试这个:

 int raiseToPower(int &base, int exponent){
   int result = 1;
   for (int i = 1; i <= exponent; i = i + 1){
      result = result * base;
    }
    return result;
 }

【讨论】:

    【解决方案3】:

    你可能想要这样的循环:

    int result = 1;
    for (int i = 0; i < exponent; i = i + 1) {
        result = result * base;
    }
    return result;
    

    此外,您通过引用将 base 参数带到 raiseToPower - 这意味着您正在更改 main 中的基本变量 - 可能不是您想要做的。

    【讨论】:

      【解决方案4】:

      让我们考虑一下这个循环

       for (int i = 1; i < exponent; i = i + 1){
         base= base * base;
         }
      

      第一次迭代后,当 i 等于 1 时,你有

         base= base * base;
      

      也就是说结果是base ^ 2

      当 i = 2 你有

         base= base^2 * base^2;
      

      也就是说结果是base^4。

      当 i 等于 3 时,你有

         base= base^4 * base^4;
      

      也就是说结果是base^8。

      当 i 等于 4 时,你有

         base= base^8 * base^8;
      

      也就是说结果是base^16。

      结果值似乎太大而无法容纳在 int 类型的对象中。

      此外,通过引用传递参数也不是一个好主意。第二个参数的类型应该是 unsigned int。

      这是一个演示程序,展示了如何实现该功能。

      #include <iostream>
      
      long long int raiseToPower( int base, unsigned int exponent )
      {
          long long int result = 1;
      
          while ( exponent-- )
          {
              result *= base;
          }
      
          return result;
      }
      
      int main() 
      {
          int base = 6;
      
          std::cout << "6^5 is " << raiseToPower(base, 5) << std::endl;
      
          return 0;
      }
      

      它的输出是

      6^5 is 7776
      

      【讨论】:

        猜你喜欢
        • 2015-05-24
        • 1970-01-01
        • 2017-08-12
        • 1970-01-01
        • 1970-01-01
        • 2022-01-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多