簡體   English   中英

一個類或對象的“sizeof”可以為零嗎?

[英]Can “sizeof” a class or object ever be zero?

我們都知道空類的大小或空類的對象將是1個字節。 我遇到了一個類的sizeof及其對象變為0的東西。該程序在語法上是正確的,因為沒有編譯或運行時錯誤。 這是未定義的行為嗎? 我試圖執行的用例有意義,看起來像一個有效的用例? 不給類中的數組提供精確的下標或大小是一個很大的錯誤嗎? 代碼段如下:

#include<iostream>
using namespace std;
class A
{
   char a[];
};
int main()
{
    A b;
    cout<<sizeof(A)<<endl;
    cout<<sizeof(b)<<endl;
    return 0;
}

輸出:

0

0

空類的sizeof是一個字節(基本上不為零),其原因類似於“確保不同的對象具有不同的地址”。

在這種情況下,當sizeof類變為零時會發生什么? 注意:也觀察到int a[]的相同行為。

它被稱為“靈活的陣列成員” ,它是C99的一個特征(我認為)。 它不是有效的C ++ - 你沒有警告/錯誤,可能是因為編譯器支持它作為擴展。

-Wall -Wextra -pedantic -std=c++NN-Wall -Wextra -pedantic -std=c++NN ,..)應該生成警告(最后兩個標志將禁用任何編譯器擴展)。


您可以在此相關問題中看到一些信息: 在C練習中使用靈活的數組成員嗎?

例如,以下是GCC對此的說法:

在ISO C99中,您將使用靈活的數組成員,它在語法和語義上略有不同:
...
靈活的數組成員具有不完整的類型,因此可能不會應用sizeof運算符。 作為零長度數組的原始實現的怪癖,sizeof的計算結果為零

(來源: https//gcc.gnu.org/onlinedocs/gcc/Zero-Length.html )。

這解釋了char a[]0大小而不是類的0,但正如我已經提到的 - 它是C特性而不是有效的C ++。

如果使用-pedantic標志進行編譯

$ g ++ -W -Wall -pedantic prog.cpp
prog.cpp:5:11:警告:ISO C ++禁止零大小數組'a'[-pedantic]

C ++不支持VLA ,因此您的類聲明不合法,超出了標准C ++規則的范圍。

你的代碼不是標准的C ++,因此我看不出任何意義。

如果你使用迂腐旗,你應該收到:

gsamaras@pythagoras:~$ g++ -pedantic file.cpp
file.cpp:5:11: warning: ISO C++ forbids zero-size array ‘a’ [-Wpedantic]
    char a[];
         ^

嘗試將班級改為

class A {
   char a[5];
};

那么你應該得到一個輸出

5
5

就像你應該期待的那樣

但是,您可以爭辯說,如果沒有標志,您的代碼會編譯並輸出零。 作為一個計數器,我可以說如果你使用這個類也一樣:

class A {
   char a[0];
};

但我很確定你知道不允許使用零大小的數組,但是這個東西編譯得很好並且輸出為0。

空基類可以優化為零字節,這在技術上會使sizeof(base)也為0

“1字節”的東西實際上是一個實現細節,來自不同對象需要具有不同地址的規則。

所以:

struct base { };

struct derived : base { };

sizeof(base)sizeof(derived)都允許為0 ,因為derived對象與包含在其中的base對象是同一個對象。

然而:

struct base1 { };
struct base2 { };
struct derived : base1, base2 { };

這里, sizeof(derived)必須為1,因為標准要求

derived d;
assert(static_cast<base1 *>(&d) != static_cast<base2 *>(&d));

同理:

struct type1 { };
struct type2 { };
struct combined { type1 obj1; type2 obj2; };

要求

combined c;
assert(&c.obj1 != &c.obj2);

許多編譯器供應商采用快捷方式,只需使空類占用一個字節。

類的大小可以是0.考慮下面的代碼

#include <iostream>
using namespace std;

class A
{
    public:
    int a[0];
    void getA(){
        cout<<"Hello World";
    }
};

class B
{
};

int main()
{
    cout<<"The size of A is "<<sizeof(A)<<endl;   // prints 0
    A w;
    cout<<"The size of object of A is "<<sizeof(w)<<endl;    //prints 0
    cout<<"The size of the array a in A is "<<sizeof(w.a)<<endl;  // prints 0
    cout<<"The value from function of class A is  "<<w.getA()<<endl;  // Gives a compilation error
    cout<<"The size of B is "<<sizeof(B)<<endl;  //prints 1
}


Output:
The size of A is 0
The size of object of A is 0
The size of the array a in A is 0
The size of B is 1

因此,訪問類中存在的大小為0的函數會導致編譯錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM