【问题标题】:First member of class of C++ objectC++ 对象类的第一个成员
【发布时间】:2014-10-12 05:26:21
【问题描述】:

我知道以下是不好的,但我的印象是类的第一个成员是类的起始地址。错了吗?

   class A{
      public:
       int a;
       int b;
   };
  
   class B{
     public :
       int x;
   };

   int main()
   {
        B *pb=new B();
        A *pa=(A*)pb;
        pa->a++;
   }

我的印象是pb->x 会增加 1。它总是 true 还是 undefined ?为什么当我们有用户定义的构造函数或虚函数时它会改变?

【问题讨论】:

  • 是的。这是坏的!太糟糕了,答案应该是无关紧要的。
  • 你的问题没关系!你能做的只是糟糕的设计和大部分未定义的行为。简单的回答:永远不要那样做!它可能今天可以工作,但没有定义它明天可以工作或与任何其他编译器一起工作。

标签: c++ class-structure


【解决方案1】:

只有当你的类是standard_layout 类型时才成立。您可以使用类型特征is_standard_layout

进行测试
 std::cout << std::is_standard_layout<A>::value << '\n';
 std::cout << std::is_standard_layout<B>::value << '\n';

对于其他类,您在内存中存储了额外的信息,这些信息是特定于编译器的,而不是标准化的。您可以查看This question,其中讨论并展示了一些内存布局。

对于您的第二个示例/问题,该标准具有以下引用(5.2.10/7,N3337 草案):

对象指针可以显式转换为不同类型的对象指针。当“指向 T1 的指针”类型的纯右值 v 转换为“指向 cv T2 的指针”类型时, 结果是 static_cast(static_cast(v)) 如果 T1 和 T2 都是标准布局类型 (3.9) 并且 T2 的对齐要求不比 T1 更严格, 或者如果任何一种类型都是无效的。将“指向 T1 的指针”类型的纯右值转换为“指向 T2 的指针”类型(其中 T1 和 T2 是对象类型,而 T2 的对齐要求是 不比 T1 更严格)并返回其原始类型会产生原始指针值。未指定任何其他此类指针转换的结果。

如果我正确阅读并解释了这一点,那么您的示例未指定,因为 A 的对齐要求大于 B 的对齐要求。但是,其他方式应该没问题,例如:

int main()
{
    A *pa=new A();
    B *pb=reinterpret_cast<B*>(pa);
    pb->x++;
    std::cout << pa->a;
}

【讨论】:

  • 您可以将指向标准布局类型对象的指针转换为指向其第一个成员的指针,但我对此并不完全确定。您可以添加来自 The Standard 的支持引用吗?
  • 这些规则中的大多数都相当直观,但规则#3 和#6 对我来说似乎很荒谬,我什至无法理解#5 想说什么。
  • @ValekHalfHeart #3 是允许编译器根据访问重新排序类成员。 #6 需要与#5 一起阅读;如果该类具有非静态数据成员,则其所有基类必须为空(根据 #5),但如果第一个非静态数据成员与基类具有相同类型,则编译器必须给出它并且(空)基类子对象不同的地址,因为它们是不同的对象。
  • @BoBTFish 我添加了描述这一点的标准部分。我不能说我是否正确解释了它,但看起来,从 A 到 B 的转换应该没问题,而从 B 到 A 的转换是未指定的。
【解决方案2】:

您通过将指针强制转换为另一个类违反了严格的别名。如果您的类是标准布局,则只能将其转换为第一个成员的类型。

【讨论】:

    【解决方案3】:

    是的,你绝对错了,你永远不能认为这样的事情是理所当然的,那些是 C++ 不保证的编译器特定的合同。

    我相信您将类与 C++ 数组混淆了:例如,指向 char 数组的第一个成员的指针与指向该数组的指针相同。

    【讨论】:

    • 规范的任何支持链接?
    • 我不太明白为什么这个答案被否决
    • 因为不正确。事实上,标准布局确实做到了这一点,甚至最初的 C 规范也做到了。
    • 如果第一个成员是层次结构中的虚函数怎么办?如果类本身是层次结构的一部分怎么办?我认为要么你不确定你在说什么(尊重),要么你没有考虑所有的可能性......
    • @jaffar exaclty 这就是标准布局所保证的。如果您的班级有任何这些“障碍”,则它不是标准布局。另一方面,如果你的类是标准布局的,那么它是明确定义的。
    猜你喜欢
    • 2015-08-17
    • 1970-01-01
    • 2012-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多