简体   繁体   English

C++ 早期绑定和后期绑定

[英]C++ early binding and late binding

I read about early and late binding in C++:我阅读了 C++ 中的早期和晚期绑定:

int add (int x, int y)
{
  return x+y;
}

int main()
{
   int a=add(5,6);//early binding
   int (*p_add)(int,int)=add;

   int b=p_add(5,19);
}

Why can't int b=p_add(5,19) be resolved at compile time?为什么不能在编译时解析int b=p_add(5,19) We all know it is associated with the add function at compile time.我们都知道它与编译时的add函数相关联。 Then why can't we resolve it at compile time same as add function?那为什么我们不能像add函数一样在编译时解析它呢? My problem is that if i know add(x,y) at compile time then I may predict p_add at compile time too.我的问题是,如果我在编译时知道add(x,y) ,那么我也可以在编译时预测p_add

Here's what gcc and Clang produce for your code as it stands right now:以下是 gcc 和 Clang 为您现在的代码生成的内容:

main:                                   # @main
    xor     eax, eax
    ret

code on Godbolt Godbolt 上的代码

So in this case, we don't really have either early or late binding.所以在这种情况下,我们实际上没有早期或晚期绑定。 Rather, we have no binding to the function at all--you didn't use the result you got from calling the function (either directly or via a pointer), so the compiler simply didn't generate any code to call the function at all.相反,我们根本没有绑定到函数——您没有使用从调用函数中获得的结果(直接或通过指针),因此编译器根本没有生成任何代码来调用函数全部。

We can repair that with code on this order:我们可以使用此订单上的代码修复它:

#include <iostream>

int add (int x, int y)
{
  return x+y;
}

int main()
{
   int a=add(5,6);//early binding
   int (*p_add)(int,int)=add;

   int b=p_add(5,19);
   std::cout << b;
}

In this case, the compiler still detect that the result of the function doesn't depend on anything at compile time, so it computes the value at compile time, and prints it out as a constant:在这种情况下,编译器在编译时仍然检测到函数的结果不依赖任何东西,因此它在编译时计算该值,并将其打印为常量:

mov esi, 24
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)ant:

Code on Godbolt Godbolt 上的代码

So, we still don't have any real "binding" to the function.所以,我们仍然没有任何真正的“绑定”到函数。 Let's have it use inputs it won't know until run-time:让我们让它使用直到运行时才知道的输入:

#include <iostream>
#include <cstdlib>

int add (int x, int y)
{
  return x+y;
}

int main()
{
    int x1 = rand();
    int x2 = rand();

   int a=add(x1, x2);//early binding
   int (*p_add)(int,int)=add;

   int b=p_add(x1,x2);
   std::cout << b;
}

This source produces the following object code:此源生成以下目标代码:

call rand
mov ebx, eax
call rand
mov edi, OFFSET FLAT:_ZSt4cout
lea esi, [rbx+rax]
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)

The compiler is still aware that the pointer consistently points to one particular function, so even though the source code shows the function being called via a pointer, in the object code we don't call the function via a pointer...and in fact, we still don't call the function at all.编译器仍然知道指针始终指向一个特定的函数,因此即使源代码显示通过指针调用函数,在目标代码中我们不通过指针调用函数......事实上,我们仍然根本不调用该函数。 Instead, the code for the body of the function has been generated inline.相反,函数体的代码已内联生成。

To get an actual function call via a pointer, we can have a pointer that refers to either of two different functions, and it won't be apparent until run-time which of the two to use in a particular case.为了通过指针获得实际的函数调用,我们可以使用一个指针来引用两个不同函数中的任何一个,并且直到运行时才能明确在特定情况下使用这两个函数中的哪一个。 For example:例如:

#include <iostream>
#include <cstdlib>

int add (int x, int y)
{
  return x+y;
}

int sub(int x, int y) { 
    return x-y;
}

int main()
{
    int x1 = rand();
    int x2 = rand();

    int z = rand() % 2;

   int (*p_add)(int,int) = z ? add : sub;

   int b=p_add(x1,x2);
   std::cout << b;
}

This (finally!) make the call via a pointer actually happen as a call via a pointer:这(终于!)使通过指针的调用实际上作为通过指针的调用发生:

  call rand
  mov edx, OFFSET FLAT:sub(int, int) ; start by assuming we'll subract
  mov esi, r12d
  mov edi, ebp
  test al, 1                         ; then see if we have an odd or even number
  mov eax, OFFSET FLAT:add(int, int)
  cmove rax, rdx                     ; if necessary, point to add
  call rax                           ; and finally call the function via the pointer
  mov edi, OFFSET FLAT:_ZSt4cout
  mov esi, eax
  call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)

Code on Godbolt Godbolt 上的代码

Summary概括

If it's apparent at compile time what function will be called, the compiler probably won't generate code to call the function via a pointer, even if that's what the source code shows.如果在编译时很明显将调用哪个函数,则编译器可能不会生成代码来通过指针调用该函数,即使源代码是这样显示的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM