我试图通过虚拟继承和 vTables/vPtrs 完全理解内存中发生的事情,以及没有发生的事情。
我有两个我编写的代码示例,我完全理解它们工作的原因,但我只是想确保我对对象内存布局有正确的想法。
Here是图片中的两个示例,我只是想知道我对所涉及的内存布局的想法是否正确。
示例 1:
class Top { public: int a; };
class Left : public virtual Top { public: int b; };
class Right : public virtual Top { public: int c; };
class Bottom : public Left, public Right { public: int d; };
示例 2:
同上,但有:
class Right : public virtual Top {
public:
int c;
int a; // <======= added this
};
最佳答案
C++ 标准并没有对对象布局说太多。虚函数表 (vtables) 和虚基指针甚至不是标准的一部分。所以问题和答案只能说明可能的实现。
快速查看您的绘图似乎显示出正确的布局。
您可能对这些进一步的引用资料感兴趣:
Multiple Inheritance Considered Useful一篇关于多继承和虚继承情况下布局的ddj文章。
Microsoft patent描述 vfptr(虚函数表,又名 vtables)和 vbptr(虚基指针)的使用。
Right::a 或 Left::a ?在您的测试 2 中,Right 和 Left 共享相同的公共(public)父级 Top。所以在 Bottom 中只有一个子对象 Top,因此,只有一个相同的 Top::a。
有趣的是,您在测试 2 中引入了 Right 中的成员 a。这是一个 a,它不同于从 Top 继承的 a。它是一个独特的成员,只是“巧合”地与另一个成员同名。因此,如果您通过 Right 访问 a,Right::a 会隐藏 Top::a(这是顺便说一句,还有 Bottom::Top::a、Right::Top::a、Left::Top::a).在这种情况下,bottom.a 表示 Right::a,不是因为对象布局,而是因为名称查找(和隐藏)规则。而且这不依赖于实现:它是标准的和可移植的。
这里是你的测试 2 的一个变体来演示这种情况:
int main() {
Bottom bottom;
bottom.a = 7;
cout << bottom.Top::a << endl << bottom.Left::Top::a << endl;
cout << bottom.Right::Top::a << endl << bottom.Left::a << endl;
cout << bottom.Right::a << endl <<endl;
bottom.Right::a = 4;
bottom.Left::a = 3;
cout << bottom.Top::a << endl << bottom.Left::Top::a << endl;
cout << bottom.Right::Top::a << endl << bottom.Left::a << endl;
cout << bottom.Right::a << endl <<endl;
cout << "And the addresses are: " << endl;
cout << " Bottom: " << (void*)&bottom << endl;
cout << " Top: " << (void*)static_cast<Top*>(&bottom) << endl;
cout << " Left: " << (void*)static_cast<Left*>(&bottom) << endl;
cout << " Right: " << (void*)static_cast<Right*>(&bottom) << endl;
cout << " Top::a: " << (void*)&bottom.Top::a << endl;
cout << " Left::Top::a: " << (void*)&bottom.Left::Top::a << endl;
cout << " Right::Top::a:" << (void*)&bottom.Right::Top::a << endl;
cout << " Left::a: " << (void*)&bottom.Left::a << endl;
cout << " Rigth::a: " << (void*)&bottom.Right::a << endl;
};
关于C++虚拟继承内存布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30870096/
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序
是否可以为特定(或所有)项目使用多个布局?例如,我有几个项目,我想对其应用两种不同的布局。一个是绿色的,一个是蓝色的(但是)。我想将它们编译到我的输出目录中的两个不同文件夹中(例如v1和v2)。我一直在玩弄规则和编译block,但我不知道这是怎么回事。因为,每个项目在编译过程中只编译一次,我不能告诉nanoc第一次用layout1编译,第二次用layout2编译。我试过这样的东西,但它导致输出文件损坏。compile'*'doifitem.binary?#don’tfilterbinaryitemselsefilter:erblayout'layout1'layout'layout2'
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
在我的系统中,我已经定义了STI。Dog继承自Animal,在animals表中有一个type列,其值为"Dog"。现在我想让SpecialDog继承自dog,只是为了在某些特殊情况下稍微修改一下行为。数据还是一样。我需要通过SpecialDog运行的所有查询,以返回数据库中类型为Dog的值。我的问题是因为我有一个type列,rails将WHERE"animals"."type"IN('SpecialDog')附加到我的查询中,所以我不能获取原始的Dog条目。所以我想要的是以某种方式覆盖rails在通过SpecialDog访问数据库时使用的值,使其表现得像Dog。有没有办法覆盖用于类型
在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p