代码之家  ›  专栏  ›  技术社区  ›  hhafez

内存中的C++对象结构与结构

  •  44
  • hhafez  · 技术社区  · 16 年前

    如果我有如下的课

       class Example_Class 
       {
           private:
             int x; 
             int y; 
           public: 
             Example_Class() 
             { 
                 x = 8;
                 y = 9;
             }
           ~Example_Class() 
           { } 
       };
    

    以及如下结构

    struct
    {
       int x;
       int y;
    } example_struct;
    

    是记忆中的结构 example_struct 西米拉尔到那个 Example_Class

    例如,如果我执行以下操作

    struct example_struct foo_struct;
    Example_Class foo_class = Example_Class();
    
    memcpy(&foo_struct, &foo_class, sizeof(foo_struct));
    

    foo_struct.x = 8 foo_struct.y = 9 (即:与foo_类中的x,y值相同)?

    我之所以要问的是,我有一个C++库(不想改变它),它用C代码共享一个对象,我想使用一个Stutt来表示来自C++库的对象。我只对对象的属性感兴趣。

    我知道最理想的情况是在C和C++代码之间有一个普通的结构包,但是在使用中改变C++库是不容易的。

    8 回复  |  直到 16 年前
        1
  •  61
  •   j_random_hacker    16 年前

    C++标准 保证 一个C的内存布局 struct 一个C++ class (或) 结构 同样的事情,只要C++ / 结构 符合存在的标准 豆荚 (纯旧数据)。那么pod是什么意思?

    类或结构是pod,如果:

    • 所有数据成员都是公共的,它们本身是pod或基本类型(但不是引用或指向成员类型的指针),或者是这样的数组
    • 它没有用户定义的构造函数、赋值运算符或析构函数
    • 它没有虚拟功能
    • 它没有基类

    关于允许的“C++ + ISM”是非虚成员函数、静态成员和成员函数。

    由于您的类既有构造函数又有析构函数,所以从形式上讲,它不属于pod类型,因此保证不成立。(尽管,正如其他人提到的,在实践中,只要没有虚拟函数,在您尝试的任何编译器上,这两个布局都可能是相同的)。

    见第[26.7]节 C++ FAQ Lite 了解更多详细信息。

        2
  •  10
  •   ChrisW    16 年前

    示例结构similar的内存结构是否与示例类中的结构相同?

    行为不能保证,它依赖于编译器。

    尽管如此,如果示例ou类不包含虚拟方法(并且不从基类继承),那么答案是“是的,在我的机器上”。

        3
  •  7
  •   Greg Hewgill    16 年前

    在您描述的情况下,答案是“可能是”。但是,如果类具有任何虚拟函数(包括可以从基类继承的虚拟析构函数),或者使用多个继承,则类布局可能不同。

        4
  •  3
  •   Nick    16 年前

    添加其他人所说的内容(例如:特定于编译器,只要您没有虚拟函数,就可能工作):

    我强烈建议使用静态断言(编译时检查),如果您这样做,sizeof(example_class)==sizeof(example_struct)。请参阅boost \u static \u assert,或等效的特定编译器或自定义构造。如果有人(或某些东西,如编译器的更改)修改类使匹配无效,那么这是一个很好的第一道防线。如果需要额外的检查,还可以运行时检查成员的偏移量是否相同,这(与静态大小断言一起)将确保正确性。

        5
  •  1
  •   Zoran Horvat    11 年前

    在C++编译器的早期,编译器首先用类更改结构关键字,然后编译。很多相似之处。

    差异来自类继承,特别是虚拟函数。如果类包含虚拟函数,那么它必须在其布局的开头有指向类型描述符的指针。另外,如果类B继承自类A,那么类A的布局首先出现,然后是类B自己的布局。

    因此,关于将类实例强制转换为结构实例的问题的确切答案是:取决于类内容。对于具有方法(构造函数和非虚拟析构函数)的特定类,布局可能是相同的。如果析构函数声明为虚拟的,那么布局在结构和类之间肯定会有所不同。

    这里有一篇文章表明,从C结构到C++类的步骤没有太大的必要性: Lesson 1 - From Structure to Class

    本文解释了如何将虚函数表引入具有虚函数的类中: Lesson 4 - Polymorphism

        6
  •  0
  •   Mike Thompson    16 年前

    C++中的类和结构是等价的,除了结构的所有成员在默认情况下都是公共的(默认情况下类成员是私有的)。这确保编译C++编译器中的遗留C代码将按预期工作。

    没有什么可以阻止您使用结构中所有的奇特C++特性:

    struct ReallyAClass
    {
        ReallyAClass();
        virtual !ReallAClass();
    
        /// etc etc etc
    };
    
        7
  •  0
  •   Chuck    16 年前

    当您想将数据传递给C时,为什么不显式地将类的成员分配给结构?这样你就知道你的代码在任何地方都可以工作。

        8
  •  -2
  •   Dominik Grabiec    16 年前

    您可能只是从结构派生类,公开或私下。然后,它将在C++代码中正确解决。