类中的C++函数是动态分配的

Are C++ functions in classes dynamically allocated?

本文关键字:动态分配 函数 C++      更新时间:2023-10-16
class myclass{
 public: void hello(){
   std::cout<<"Hello"<<"n";
 }
}
myclass* mc = new myclass;
mc->hello();

功能hello动态分配,还是不动态分配?

函数不是对象(至少在C++中),并且没有生存期。 他们就在那里。 永远永远。 (同样,从C++的角度来看。

函数根本不是"分配"的。在引擎盖下,非虚函数与类没有固有的物理依附。成员函数只是普通独立函数上的一层薄薄的句法糖。例如,在您的案例中,成员函数hello被转换为普通的独立函数

void myclass_hello(myclass *this) {
  std::cout<<"Hello"<<"n";
}

当你打电话时

mc->hello();

编译器实质上将此调用替换为

myclass_hello(mc);

在C++的早期,当许多C++编译器被实现为C编译器的前端时,这正是C++成员函数转换为C函数的方式。

成员函数和普通独立函数在"分配"方面没有区别。只有一个成员函数实例本身存在,无论您创建多少个该类型的对象。

对于虚函数,事情变得有点复杂,但这仍然不需要"分配"成员函数。虚拟成员函数的每个版本只有一个实例,它仍然独立于实际对象存在。

当你进入 C++ 的内部时,你会发现编译器对代码做了各种疯狂的事情,比如完全更改函数的名称以支持函数重载。 函数不是C++中的对象,而是对函数表的引用。 我认为您想知道的是,如果您将方法放在类之外是否更好,因为该类的每个实例都没有"副本"。 事实是,您不会获得函数的"副本",但会获得指针变量的副本?答案是否定的,c++ 只会分析代码并将单个函数调用放在您使用它的任何位置。 当它将代码中的变量名称转换为实际内存位置时,将考虑任何引用"this"或实例数据。

当涉及函数时,不会分配内存。

这些只是可执行文件中的一堆代码

hello 的实际代码只有一个实例,它在程序运行时位于可执行文件中/加载到内存中。 类(对象)的所有实例都使用代码的一个实例。

hello 方法的机器代码是在编译时生成的。 由于它不是虚拟方法,因此编译器可以确定如何直接调用它。 等效代码可能是:

struct MyStruct {};
void hello(MyStruct* this)
{
  std::cout << "Hello" << std::endl;
}
int main(int, char**)
{
  MyStruct* ms = new MyStruct;
  hello(ms);
  return 0;
}

这完全取决于上下文,更准确地说,它是什么样的功能。你永远不会分配一个函数,因为它是代码而不是数据,唯一可以动态的是在每个类的基础上调用哪些函数,这些是虚函数。

这是一个普通的类成员函数:

void MyClass::CallFunction()
{
}

实际上,编译器,并且C++很多编译器都这样做,添加一个通常"不可见"但同时可访问的函数参数,该参数通常是列表中的第一个,类对象的内存指针,*this。

void MyClass::CallFunction(MyClass *this)
{
}

如果你声明成员函数 static ,你基本上创建一个在类范围内但不是类一部分的函数,因此它没有 this 指针。

由于作用域,编译器会自动引用您的类变量,因此您不必这样做,因此可以使用 访问属于类对象的任何内容

this->classVariable = 0;

对于虚函数,编译器创建了一个由编译器处理的 vtable,因此函数覆盖和多态性实际上可以工作。vtable 仅存储指向函数的指针,因此即使在这种情况下函数也是固定的。

由编译器决定在类对象中实际

分配哪些部分,这些通常是非常量非静态成员变量,因此您可以将实际对象视为所有子类和主类中存在的所有变量的简单结构。