结构定义与结构声明和存储生成

时间:2015-11-25 05:07:00

标签: c++ c struct declaration

来自Scope Regions in C++

  

在C中,结构声明永远不会生成存储,因此C不会   将结构定义与其他结构声明区分开来。 C ++   确实。在C ++中,结构声明也是一个定义,如果它有一个   身体,如:

private void MyWnd::onTextChanged()
{
    QStringList wordList = textEdit->toPlainText().split();
    foreach (QString word, wordList )
    {
        qDebug() << word;
    }
}
     

如果它缺少一个正文,它只是一个声明,如:

     

struct widget // a definition { ... };

那么struct widget; // just a declaration声明在哪些情况下会在c ++中生成存储?

2 个答案:

答案 0 :(得分:3)

以下是我对上述内容的解释,希望更清楚。

  

struct声明永远不会在C或C ++中生成存储。

     

由于C不区分结构定义和其他结构声明,因此结构定义也不会在C中生成存储。

     

在C ++中,带有静态数据成员的结构的定义( nb在C 中没有静态数据成员这样的东西)不能自己生成存储,而是正式声明它静态数据成员,然后需要在封闭范围内定义 - 此时它实际上会生成存储。

换句话说,结构的C ++定义在技术上并不能生成存储,但实际上不能使用,除非其静态数据成员在其他地方定义(使用隐含存储 - 即使没有任何对象该类型是实例化的。)

下面的相关C ++参考资料。

- 3.1.2声明和定义

struct X { // defines X
    static int y; // declares static data member y
};

int X::y = 1; // defines X::y

- 9.4.2静态数据成员

  

9.4.2.1 [...]静态数据成员不是类的子对象的一部分。该类的所有对象只共享一个静态数据成员的副本。

     

[...]在类定义中声明静态数据成员不是一个定义,除了cv-quali fi ed void之外,它可能是一个不完整的类型。

     

[...]静态数据成员的定义应出现在包含成员类定义的命名空间范围内。

     

[...]注意:一旦定义了静态数据成员,即使没有创建其类的对象,它也存在。

答案 1 :(得分:3)

两种情况都没有。问题归结为你链接的文章最好是误导,如果不是错误的话。文章实际上并没有说&#34;生成存储&#34;是两者的必然结果,但它误导了它。我认为,这个措辞很差,而且非常不精确。

不幸的是,标准也不容易阅读,请参阅第3.1节:{http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf][1]

简而言之,对于结构定义,声明只引入了类型名称或结构标记&#34; widget&#34;。该定义是一个声明,也提供了定义&#34;定义的主体。类型,就像第一个例子一样。

C ++标准中的示例更容易理解:

  

示例:以下所有内容均为定义:

int a;                       // defines a
extern const int c = 1;      // defines c
int f(int x) { return x+a; } // defines f and defines x
struct S { int a; int b; };  // defines S, S::a, and S::b
struct X {                   // defines X
    int x;                   // defines non-static data member x
    static int y;            // declares static data member y
    X(): x(0) { }            // defines a constructor of X
};
int X::y = 1;                // defines X::y    
enum { up, down };           // defines up and down
namespace N { int d; }       // defines N and N::d
namespace N1 = N;            // defines N1
X anX;                       // defines anX
     

而这些只是声明:

extern int a;       // declares a
extern const int c; // declares c
int f(int);         // declares f
struct S;           // declares S
typedef int Int;    // declares Int
extern X anotherX;  // declares anotherX
using N::d;         // declares d

你可以定义&#34;一种除了定义它的布局之外什么都不做的结构。但你也可以定义&#34;该结构类型的变量。那就是存储可能会被生成&#34; (我可能会说分配或保留)。当定义结构类型的全局变量时,它将导致二进制可执行文件包含结构大小的数据块。如果定义了本地(自动或堆栈)变量,则会在运行时占用执行堆栈上的空间。

例如,如果是全局的(即不在函数中):

struct widget x; // defines variable x of type struct widget
                 // which must be defined somewhere prior

struct widget2; // declares structure widget2
// does nothing except tells the compiler there will be some
// structure definition named widget2 coming later

int fn(widget2 *p); // OK widget2 need only be *declared* first

// NO
// struct widget2 y; // illegal - has not be defined yet

struct widget2 // defines structure widget2 that *would* take up ~8 bytes
{
    int thing1;
    int thing2;
} y; // defines variable y of type struct widget2 that *does* take up ~8 bytes

struct widget2 z[10]; // defines global variable z that *does* take up ~80 bytes

另一种看待它的方法是定义类型与定义变量根本不同。类型是在编译时存在的概念,在运行时不占用空间(忽略RTTI)。

C和C ++标准区分了声明和定义,因为除了其他原因之外,你不能有多个不同的定义,但你可以多次声明它。对于变量,定义大致与存储分配一致,但这并不是区分的主要原因。