C++编译器如何实际传递参考参数?

T.E*_*.D. 15 c++ parameter-passing

这个问题是由于一些混合语言编程而产生的.我有一个我想用C++代码调用的Fortran例程.Fortran通过引用传递其所有参数(除非您另有说明).

所以我认为在我的C++代码中我会聪明(糟糕的开始)并定义类似这样的Fortran例程:

extern "C" void FORTRAN_ROUTINE (unsigned & flag);
Run Code Online (Sandbox Code Playgroud)

这段代码工作了一段时间,但(当然,当我需要离开时)突然开始吹回电话.清除指示一个munged调用堆栈.

一位工程师来到我身后,解决了这一问题,宣布该程序必须在C定义++作为

extern "C" void FORTRAN_ROUTINE (unsigned * flag);
Run Code Online (Sandbox Code Playgroud)

除了两件事,我接受了.一个是编译器不通过引用传递引用参数似乎相当直观,而且我无法在任何地方找到这样的文档.另一个是他同时在那里改变了大量其他代码,所以理论上它可能是另一个修改问题的修改.

所以问题是,C++如何实际传递参考参数?是否可以免费为小值或其他东西进行复制,复制?换句话说,参考参数在混合语言编程中是完全无用的吗?我想知道所以我再也没有犯同样的代码杀戮错误.

GMa*_*ckG 9

C++没有定义实现应该如何,它只是一种语言.所以没有"一个"引用的实现.

也就是说,引用是用指针实现的.这导致了很多混乱("引用只是指针","引用只是指出了普通部分的指针")但事实并非如此.引用是别名,并且始终是别名.

编译器将传递变量的地址,并使用该指针进行操作.这具有相同的效果(但不一样的语义!).更具体地说,编译器可以"替换"这个:

void make_five(int& i)
{
    i = 5;
}

int main(void)
{
    int i = 0;
    make_five(i);
}
Run Code Online (Sandbox Code Playgroud)

有了这个:

void make_five(int* const i)
{
    *i = 5;
}

int main(void)
{
    int i = 0;
    make_five(&i);
}
Run Code Online (Sandbox Code Playgroud)

(在实践中,这样一个简单的函数将被内联,但你明白了.)因此,你的同事建议你使用指针.

请记住,参考是首选.这是引用和指针之间的区别很重要的地方.你想为变量添加别名,还是想指向它?大多数时候,前者.在C中,您必须使用指针来执行此操作,这会导致常见的C程序员误解,即引用实际上是指针.

要获得类似的语义(因为您现在指向一个变量,而不是别名),您应该确保指针的值不为null:

extern "C" void FORTRAN_ROUTINE (unsigned * flag)
{
    assert(flag); // this is normally not a problem with references, 
                  // since the address of a variable cannot be null.

    // continue...
}
Run Code Online (Sandbox Code Playgroud)

为了安全起见.


Vic*_*Liu 4

只是为了插话,我相信你是对的。我一直使用引用将参数传递给 Fortran 函数。根据我的经验,在 Fortran-C++ 接口上使用引用或指针是等效的。我已经使用 GCC/Gfortran 和 Visual Studio/Intel Visual Fortran 尝试过此操作。它可能依赖于编译器,但我认为基本上所有编译器都通过指针传递来实现引用。