【问题标题】:C++ Passing By Reference Not Changing ArgumentC++ 通过引用传递不改变参数
【发布时间】:2018-03-05 08:32:46
【问题描述】:

我已经盯着这个看了大约一个小时,老实说,我不知道我错过了什么。

#include <iostream>

using namespace std;

void callChain();

double chain(int, int &, int &);

int main()
{
    callChain();
}

void callChain() {
    int totalInches = 53;
    int feet;
    int inches;

    cout << "\nTesting chain for 53 inches: \nExpected result: 15.46 feet: 4 inches: 5" << endl;
    cout << "Actual result: " << chain(totalInches, feet, inches) << " feet: " << feet << " inches: " << inches << endl;
}

double chain(int totalInches, int &feet, int &inches) {
    feet = totalInches / 12;
    inches = totalInches % 12;

    return (feet) * 3.49 + (inches) * .30;
}

返回是正确的,所以显然该功能正在工作,但对于我来说,我无法弄清楚为什么英尺和英寸没有改变。一切都拼写正确,我有所有的 &

【问题讨论】:

  • 未指定输出中发生的事情的顺序。您不知道feetincheschain() 函数调用的评估顺序。
  • 检查这个问题及其答案:stackoverflow.com/q/8931249/5958455
  • 为了说明事情的不确定性,我将您的代码逐字粘贴到 jdoodle for g++ 14 GCC 7.20 中,得到了您期望的答案。 :)

标签: c++


【解决方案1】:

请记住,&lt;&lt; 是函数调用的语法糖,这些函数的求值顺序不一定是您认为的顺序。事实上,C++ 实际上并没有指定顺序。所以你第二个cout 的最后部分正在打印出feetinches 的起始值。

在第二个cout 之前的中间步骤中调用chain(totalInches, feet, inches),甚至可以采用这种方式(确认@DavidSchwartz):

cout << "Actual result: " << chain(totalInches, feet, inches);
cout << " feet: " << feet << " inches: " << inches << endl;

【讨论】:

  • 或者只是:cout &lt;&lt; "Actual result: " &lt;&lt; chain(totalInches, feet, inches); cout &lt;&lt; " feet: " &lt;&lt; feet &lt;&lt; " inches: " &lt;&lt; inches &lt;&lt; endl;
【解决方案2】:

根据ostream chaining, output order,ISO C++ 标准中未指定评估顺序

为确保在访问这些变量之前调用函数,请将输出链分开:

cout << "Actual result: " << chain(totalInches, feet, inches);
cout << " feet: " << feet << " inches: " << inches << endl;

【讨论】:

  • 自 C++17 起,计算顺序严格从左到右。我还为您链接的问题添加了一个较晚的答案。
【解决方案3】:

只是为了更好地说明迄今为止给出的答案(提供更多细节):

std::cout &lt;&lt; xoperator&lt;&lt;(std::cout, x) 的语法糖;当operator&lt;&lt; 返回它的第一个参数时,std::cout &lt;&lt; x &lt;&lt; y; 得到:

operator<<(operator<<(std::cout, x), y);

显然,外部调用的第一个参数将在外部调用实际执行之前被评估(例如,内部调用执行)——这就是任何保证已经结束的地方,即。 e.由于未指定参数评估的顺序,因此编译器可以在调用内部运算符之前评估 y - 包括评估后者的参数!

operator<<(operator<<(std::cout, f(x)), x);

同样,这里唯一的保证是 f(x) 在调用内部运算符之前调用,并且在调用外部运算符之前调用内部运算符;不过,原始的x 可以在第一时间进行评估...

显然,您的编译器会从最后一个到第一个开始评估参数,这很可能是由于使用了调用约定(很可能是 cdecl;在 Windows 上可能是 stdcall)...

已接受答案的更改在函数调用之间引入了一个序列点(旧的,C++11 之前的措辞),它确保在调用下一个函数之前完成前一个调用的所有效果,即。 e. (使用新的 C++11 措辞):

operator<<(std::cout, f(x)); // is sequenced  b e f o r e  next line
operator<<(std::cout, x);    // is sequenced  a f t e r  previous line

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-14
    • 2012-01-04
    • 2010-10-07
    • 1970-01-01
    • 2011-10-07
    • 2016-05-13
    相关资源
    最近更新 更多