【问题标题】:Why does passing by reference to two functions at once cause it to not change reference value?为什么一次通过引用传递两个函数会导致它不改变引用值?
【发布时间】:2013-12-16 01:10:45
【问题描述】:

所以,我编写了将整数更改为 int 数组的简单函数(对于 long int 计算,现在我想我可以使用 std::stoi...),但它没有返回我期望的结果.

int main(){
int l=0;
printIntArray(toArray(12345,l),l);
return 0;
}

void printIntArray(int* a, int n, char separator){
for(int i=0;i<n;i++)
    std::cout<<a[i]<<separator;
std::cout<<std::endl;
}
void printIntArray(int* a, int n){
for(int i=0;i<n;i++)
    std::cout<<a[i];
std::cout<<std::endl;
}

int power(int a, int p){
for(int i=0;i<p;i++)
    a*=a;
return a;
}

int* toArray(int a, int& l){
l=1;
int p=10;
//find how many digits are there
for(;p<=a;p*=10){
    l++;
}
p/=10;

int* result = new int[l];
for(int i=0;i<l;i++){
    result[i]=a/p;
    a-=result[i]*p;
    p/=10;
}
return result;
}

问题是,当我调试 printIntArray 时,l 的值为 0。但是,在调用 print 之前,调用了 toArray,这应该改变它的长度。如果我将 main 划分为

int main(){
int l=0;
int* t=toArray(12345,l);
printIntArray(t,l);

return 0;
}

它给了我正确的结果。这是为什么? (我使用的是 Visual Studio 2010)

【问题讨论】:

  • 函数调用中的求值顺序是未指定的,并且依赖于特定的顺序,您的代码会调用未定义的行为。
  • 对于 C++,代码中没有实际的 reference,只有指针。
  • @H2CO3 好奇。尽管如此,为什么它在 debiggin 时以“正确”的顺序评估函数? (奇怪的是离开函数后没有保留更改)
  • @JoachimPileborg 我现在感觉像勺子场景中的 Neo ......没有参考。
  • @Xyzk IDK。这是一个实现细节(首先,UB就是UB。无法解释。)

标签: c++ parameters parameter-passing


【解决方案1】:

问题在于函数参数中评估变量的顺序。VS 中的默认调用约定是 __cdecl - 它以相反的顺序(从右到左)将参数推入堆栈。因此,在您的示例中,它首先将 l=0 推送到 printIntArray,然后才调用 toArray(更改 l 值)。

参考http://msdn.microsoft.com/en-us/library/vstudio/984x0h58%28v=vs.100%29.aspx

【讨论】:

    【解决方案2】:

    __cdecl 函数调用(C 风格 - C/C++ 中的默认值)中,参数从右到左存储在堆栈中。一些编译器也会按照这个顺序进行计算。

    我不确定标准是否规定了任何内容,但依靠参数评估的顺序并不是一个好主意。这样的错误很难找到。

    我只能建议避免任何关于参数评估顺序的先验知识。

    顺便说一句,你的问题在工作面试中被问到:)

    这里会打印什么?

    int i = 0;
    printf("%d %d", ++i. i++);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-15
      • 2021-02-27
      • 2014-12-21
      • 1970-01-01
      • 2012-02-14
      • 2018-12-30
      • 2020-12-17
      相关资源
      最近更新 更多