Jac*_*ieg 4 c++ memory pointers memory-management
这是一个简单的C++类:
class A
{
public:
explicit A() : m_a(0) { }
explicit A(int a) m_a(a) { }
int getA() const { return m_a; }
void setA(int a) { m_a = a; }
private:
int m_a;
}
Run Code Online (Sandbox Code Playgroud)
这是我目前所知道的:
sizeof(A) = sizeof(int) = sizeof(m_a)这是我不知道的:
成员函数存储在哪里以及它们实际存储的方式?假设int例如存储在4个字节上; 我可以想象RAM内存布局有4个连续的单元格,每个单元格存储一部分int.我怎么能想象一个函数的这个布局?(这听起来很傻,但我想函数必须在内存中占有一席之地,因为你可以指向它们的指针).还存储了功能指令的方式和位置?我的第一个看法是函数和函数指令存储在程序可执行文件(及其动态或静态库)中,但如果这是真的,那么在创建函数指针时会发生什么?AFAIK函数指针指向RAM内存中的位置,它们是否可以指向程序二进制文件中的位置?如果是,这是如何工作的?
任何人都可以向我解释这是如何工作的,并指出我所知道的是对还是错?
Bas*_*tch 11
首先,您需要了解链接器的作用以及可执行文件(通常在虚拟内存中执行)和地址空间和进程.在Linux上,阅读有关ELF和execve(2)系统调用的信息.另请阅读Levine的连接器和装载机书籍和操作系统:三个简单的部分.
成员函数可以是虚函数或普通函数.
普通(非virtual)成员函数就像一个C函数(除了它具有this隐式的,通常是第一个参数).例如,您的getA方法实现类似于以下C函数(在对象之外,例如在二进制可执行文件的代码段中):
int C$getA(A*thisptr) const { return thisptr->m_a; }
Run Code Online (Sandbox Code Playgroud)
然后想象编译器正在翻译p->getA()成C$getA(p)
甲虚拟成员函数被直通大致实现虚函数表(虚拟方法表).具有一些虚拟成员函数(包括析构函数)的对象通常作为其第一个(隐式)成员字段指向这样的表(由编译器在别处生成).你class A没有任何虚拟方法,但想象一下如果它有一个额外的virtual void print(std::ostream&);方法,那么你class A将拥有相同的布局
struct A$ {
struct A$virtualmethodtable* _vptr;
int m_a;
};
Run Code Online (Sandbox Code Playgroud)
而虚拟表可能是
struct A$virtualmethodtable {
void (*print$fun) (struct A$*, std::ostream*);
};
Run Code Online (Sandbox Code Playgroud)
(所以添加其他虚函数意味着只需在vtable中添加插槽); 然后调用就像p->print(std::cout);将被翻译一样
p->_vptr.print$fun(p,&std::cout);...此外,编译器将生成各种虚拟方法表作为常量表(每个类一个).
注意:多重或虚拟继承的事情更复杂.
在这两种情况下,成员函数都不会占用对象中的任何额外空间.如果它是非虚拟的,它只是一个普通函数(在代码段中).如果是虚拟的,则它在虚拟方法表中共享一个槽.
NB.如果您使用最近的GCC(即with g++)进行编译,则可以传递它,例如-fdump-tree-all标志:它将生成数百个转储文件,部分显示转储的文本形式 - 编译器的一些内部表示,您可以使用寻呼机进行检查(例如less)或文本编辑器.您也可以使用MELT或查看用g++ -S -fverbose-asm -O1.... 生成的汇编代码.
| 归档时间: |
|
| 查看次数: |
4272 次 |
| 最近记录: |