C ++:Structs和Classes真的一样吗?

时间:2012-10-08 04:04:31

标签: c++ class struct

  

可能重复:
  What are the differences between struct and class in C++

这个问题已被提出并得到了很多回答,但每隔一段时间我就会遇到令人困惑的事情。

总而言之,C ++结构和类之间的区别是着名的默认公共访问和私有访问。除此之外,C ++编译器对结构的处理方式与处理类的方式相同。结构可以有构造函数,复制构造函数,虚函数。结构的内存布局与类的内存布局相同。而C ++结构的原因是与C的后向兼容性。

既然人们对使用哪一个,结构或类感到困惑,那么经验法则是你只有普通的旧数据,使用结构。否则使用一个类。而且我已经读过结构化很好的序列化,但不是来自它。

然后有一天我遇到了这篇文章:http://www.codeproject.com/Articles/468882/Introduction-to-a-Cplusplus-low-level-object-model

它说如果我们(直接引用):

struct SomeStruct
{ 
    int    field1;
    char   field2;
    double field3;
    bool   field4; 
};  

然后这个:

void SomeFunction()
{
    SomeStruct someStructVariable;
    // usage of someStructVariable
    ... 
}  

和此:

void SomeFunction()
{ 
    int    field1;
    char   field2;
    double field3;
    bool   field4;      
    // usage of 4 variables
    ... 
}

是一样的。

它表示如果我们有一个结构或只是写下函数内部的变量,生成的机器代码是相同的。当然,这只适用于你的结构如果是POD。

这是我感到困惑的地方。在Effective C ++中,Scott Meyers说没有空类。

如果我们有:

class EmptyClass { };

它实际上是由编译器编写的,例如:

class EmptyClass
{
    EmptyClass() {}
    ~EmptyClass() {}
    ...
};

所以你不会有一个空课。

现在,如果我们将上述结构更改为类:

class SomeClass
{ 
    int  field1;
    char field2 
    double field3;
    bool  field4; 
}; 

是否意味着:

void SomeFunction()
{
    someClass someClassVariable;
    // usage of someClassVariable
    ... 
}  

和此:

void SomeFunction()
{ 
    int  field1;
    char field2 
    double field3;
    bool  field4;      
    // usage of 4 variables
    ... 
}

在机器说明方面是一样的吗?没有调用someClass构造函数?或者分配的内存与实例化类或单独定义变量相同?填充怎么样?结构和类做填充。在这些情况下,填充是否相同?

如果有人能够对此有所了解,我真的很感激。

4 个答案:

答案 0 :(得分:2)

我认为该文章的作者是错误的。虽然可能两个函数的struct和非成员变量布局版本之间没有区别,但我不认为这是有保证的。我能想到的唯一可以保证的是,因为它是一个POD,结构的地址和第一个成员是相同的......并且每个成员在某个时刻之后会在内存中跟进。

在任何一种情况下,由于它是POD(并且类也可以,不要犯这样的错误),数据是否会被初始化。

我建议不要做出这样的假设。如果您编写了利用它的代码,并且我无法想象您为什么要这样做,那么大多数其他开发人员都会觉得它令人费解。只有你必须打破法律书籍。否则更喜欢以人们习惯的方式编码。所有这一切中唯一重要的部分是你应该记住POD对象没有被初始化,除非你明确这样做。

答案 1 :(得分:2)

唯一的区别是结构的成员默认是公共的,而类的成员默认是私有的(当我默认说,我的意思是“除非另有说明”)。看看这段代码:

#include <iostream>
using namespace std;

struct A {
 int x;
 int y;
};

class A obj1;

int main() {
  obj1.x = 0;
  obj1.y = 1;
  cout << obj1.x << " " << obj1.y << endl;
  return 0;
}

代码编译并运行得很好。

答案 2 :(得分:1)

除了保护的默认值之外,结构和类之间没有区别(请注意,基类的默认保护类型也不同)。书籍和我20多年的经验告诉我们。

关于默认的空ctor / dector。标准不是要求这个。然而,一些编译器可能会生成这对空的ctor / dector。每个合理的优化器都会立即抛弃它们。如果在某个地方调用无效的函数,你怎么能检测到这个?除了消耗CPU周期之外,这会如何影响任何事情?

MSVC没有生成无用的功能。认为每个好的编译器都会这样做是合理的。

关于例子

struct SomeStruct
{ 
    int    field1;
    char   field2;
    double field3;
    bool   field4; 
}; 

void SomeFunction()
{ 
    int    field1;
    char   field2;
    double field3;
    bool   field4;      
   ... 
}

填充规则,内存顺序等可能并且很可能完全不同。优化器可能很容易丢弃未使用的局部变量。更不可能(如果可能的话)优化器将从结构中删除数据字段。为此,结构应该在cpp文件中定义,应该设置某些标志等等。

我不确定您是否会在堆栈上找到有关填充本地变量的任何文档。 AFAIK,这是制作此布局的100%编译器。相反,描述了结构/类的布局,有#pargma和控制它的命令行键等。

答案 3 :(得分:1)

  

在机器说明方面是一样的吗?

没有理由不这样做。但是标准没有保证。

  

没有调用someClass构造函数?

是的,有一个对构造函数的调用。但构造函数不起作用(因为所有成员都是POD,并且您声明someClass someClassVariable;的方式导致值初始化,这对POD成员没有任何作用)。因此,由于没有工作要做,所以不需要提供任何指示。

  

或者分配的内存与实例化类或单独定义变量相同?

该类可能包含填充,单独声明变量。
此外,我确信编译器可以更轻松地优化各个变量。

  

那么填充呢?

是的,结构(struct / class)中可能存在填充。

  

结构和类做填充。在这些情况下,填充是否相同?

是。只要确保你比较苹果和苹果(即)

struct SomeStruct
{ 
    int    field1;
    char   field2;
    double field3;
    bool   field4; 
}; 
class SomeStruct
{ 
  public:           /// Make sure you add this line. Now they are identical.
    int    field1;
    char   field2;
    double field3;
    bool   field4; 
};