c++ - C++ 编译器实际上是如何传递引用参数的?

标签 c++ parameter-passing

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

所以我认为我会在我的 C++ 代码中很聪明(从那里开始不好),并像这样定义 Fortran 例程:

extern "C" void FORTRAN_ROUTINE (unsigned & flag);

这段代码工作了一段时间,但(当然是在我需要离开的时候)突然在回电时开始崩溃。清除调用堆栈的指示。

另一位工程师在我身后解决了这个问题,宣布例程必须在 C++ 中定义为

extern "C" void FORTRAN_ROUTINE (unsigned * flag);

我会接受,除了两件事。一是编译器不通过引用传递 reference parameters 似乎相当违反直觉,而且我在任何地方都找不到任何说明这一点的文档。另一个是他同时更改了一大堆其他代码,所以理论上它可能是另一个解决问题的更改。

那么问题来了,C++实际上是如何传递引用参数的呢?是否可以免费为小值进行复制,复制或其他操作?换句话说,引用参数在混合语言编程中完全没用吗?我想知道,这样我就不会再犯同样的代码杀死错误了。

最佳答案

C++ 没有定义实现的方式,它只是一种语言。所以没有引用的“a”实现。

也就是说,引用是用指针实现的。这会导致很多困惑(“引用只是指针”、“引用只是去掉了平凡部分的指针”)但不是的情况。引用是别名,并且永远是别名。

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

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

int main(void)
{
    int i = 0;
    make_five(i);
}

有了这个:

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

int main(void)
{
    int i = 0;
    make_five(&i);
}

(实际上,这样一个简单的函数会被内联,但你明白了。)因此你的同事建议你使用指针。

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

为了获得相似的语义(因为你现在指向一个变量,而不是给它起别名),你应该确保指针的值不为空:

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...
}

只是为了安全。

关于c++ - C++ 编译器实际上是如何传递引用参数的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2936805/

相关文章:

javascript - 如何将值 'undefined' 传递给具有多个参数的函数?

CakePHP 将参数传递给 Action

variables - 在经典ASP中传递变量

c++ - 从一组集合 { {..}, {..}, {..} } 中挑选数字集合 {1,2,3} 使得所有元素都是唯一的

c++ - 我如何在 C 中要求 "at least"一个 int 的大小

c++ - 将套接字绑定(bind)到非临时端口范围内的空闲端口

c++ - 在 C++ 中存储泛型值及其类型 : merge type+value in one class or separating them?

C++传递结构函数作为继承结构中函数的参数

C++ 将内部结构作为参数传递

c++ - 如何使用 QuantLib 计算单名债券价格?