天天看點

定義一個空類型,裡面沒有任何成員變量和成員函數。對該類型求sizeof 結果?

劍指offerP23頁

定義一個空類型,裡面沒有任何成員變量和成員函數。對該類型求sizeof 結果?

結果為1 。

為什麼不是0?

       空類型執行個體中不包含任何資訊,但是當我們聲明該類型的執行個體的時候,它必須在記憶體中占有一定的空間,否則無法使用這些執行個體。至于占多少空間,由編譯器決定。Visual Studio中每個空類型的執行個體占用1位元組的空間。

如果在該類型中添加一個構造函數和析構函數,再對該類型求sizeof,得到的結果又是多少?

       還是1.調用構造函數和析構函數隻需要知道函數的位址即可,而這些函數的位址隻與類型相關,而與類型的執行個體無關,編譯器也不會因為這兩個函數而在執行個體中添加任何額外的資訊。

如果析構函數标記為虛函數呢?

      C++編譯器一旦發現一個類型中有虛函數,就會為該類型生成虛函數表,并在該類型的每一個執行個體中添加一個指向虛函數表的指針。在32位機器上,一個指針占4個位元組的空間,因而sizeof得到4;如果是64位的機器,一個指針占8位元組的空間,結果為8。

定義一個空類型,裡面沒有任何成員變量和成員函數。對該類型求sizeof 結果?
#include <iostream>

using namespace std;

class X {
	
};

class Y: public virtual X{
	
}; 

class Z : public virtual X {

};

class A : public Y, public Z {

};

int main() {
    int x = 0;
    x = sizeof X;
    cout <<"x:"<<x <<endl;  //result 1

    int y = 0;
    y = sizeof Y;
    cout << "y:" << y << endl; //result 4

    int z = 0;
    z = sizeof Z;
    cout << "z:" << z << endl; //result 4

    int a = 0;
    a = sizeof A;
    cout << "a:" << a << endl; //result 8

    system("pause");
    return 0;
}
           
定義一個空類型,裡面沒有任何成員變量和成員函數。對該類型求sizeof 結果?

    C++标準規定類的大小不為0,空類的大小為1,當類不包含虛函數和非靜态資料成員時,其對象大小也為1。因為在聲明該類的執行個體的時候,必須在記憶體中占有一定的空間,否則無法使用這些執行個體。

對有虛函數的類來說,必須為它的對象提供運作時類型資訊(RTTI,Run-Time Type Information)和關于虛函數表的資訊,常見的做法是在對象中放置一個指向虛函數表的指針,此外,為了支援RTTI,許多編譯器都把該類型資訊放在虛函數表中。但是,是否必須采用這種實作方法,C++标準沒有規定,主流編譯器均采用的一種方案。

虛函數、成員函數[包括靜态與非靜态]、和靜态資料成員都是不占用對象的存儲空間的

對象大小  =  虛函數指針  +   所有非靜态資料成員大小   +   因對齊而多占的位元組

例子:

#include <iostream>  
using namespace std;

class   A
{
};

class   B
{
    char   ch;
    void   func() {  }
};

class   C
{
    char   ch1;             //占用1位元組  
    char   ch2;             //占用1位元組  
    virtual   void   func() { }
};

class   D
{
    int   in;               //占用4位元組 
    virtual   void   func() {}
};

int  main()
{
    A   a;
    B   b;
    C   c;
    D   d;
    cout << sizeof(a) << endl;//result=1  
    cout << sizeof(b) << endl;//result=1  
    cout << sizeof(c) << endl;//result=8,本來使用6個位元組就可以,但是需要補齊    
    cout << sizeof(d) << endl;//result=8     

    system("pause");
    return 0;
}
           

參考:https://www.nowcoder.com/questionTerminal/15f2db4c495b42afa2457e589e1f7098?orderByHotValue=1&page=1&onlyReference=false

來源:牛客網

C++ sizeof關鍵字的使用總結:

1. 定義

       sizeof是一個操作符(operator)。 其作用是傳回一個對象或類型所占的記憶體位元組數。 其傳回值類型為size_t。(size_t在頭檔案stddef.h中定義,它依賴于編譯系統的值,一般定義為 typedef unsigned int size_t;)

2. 文法

sizeof有三種文法形式:

    1)  sizeof (object);  //sizeof (對象)

    2)  sizeof object;   //sizeof 對象

    3)  sizeof (type_name);  //sizeof (類型)

對象可以是各種類型的變量,以及表達式(一般sizeof不會對表達式進行計算)。

sizeof對對象求記憶體大小,最終都是轉換為對對象的資料類型進行求值。

sizeof (表達式); //值為表達式的最終結果的資料類型的大小

例子:

int i;  
sizeof(int); //值為4  
sizeof(i); //值為4,等價于sizeof(int)  
sizeof i; //值為4  
sizeof(2); //值為4,等價于sizeof(int),因為2的類型為int  
sizeof(2 + 3.14); //值為8,等價于sizeof(double),因為此表達式的結果的類型為double  
char ary[sizeof(int) * 10]; //OK,編譯無誤  
           

1. 基本資料類型的sizeof

         這裡的基本資料類型是指short、int、long、float、double這樣的簡單内置資料類型。

由于它們的記憶體大小是和系統相關的,是以在不同的系統下取值可能不同。

2. 結構體的sizeof

結構體的sizeof涉及到位元組對齊問題。

為什麼需要位元組對齊?計算機組成原理教導我們這樣有助于加快計算機的取數速度,否則就得多花指令周期了。為此,編譯器預設會對結構體進行處理(實際上其它地方的資料變量也是如此),讓寬度為2的基本資料類型(short等)都位于能被2整除的位址上,讓寬度為4的基本資料類型(int等)都位于能被4整除的位址上,依次類推。這樣,兩個數中間就可能需要加入填充位元組,是以整個結構體的sizeof值就增長了。

位元組對齊的細節和編譯器的實作相關,但一般而言,滿足三個準則:

1) 結構體變量的首位址能夠被其最寬基本類型成員的大小所整除。

2) 結構體的每個成員相對于結構體首位址的偏移量(offset)都是成員大小的整數倍,如有需要,編譯器會在成員之間加上填充位元組(internal adding)。

3) 結構體的總大小為結構體最寬基本類型成員大小的整數倍,如有需要,編譯器會在最末一個成員後加上填充位元組(trailing padding)。

注意:空結構體(不含資料成員)的sizeof值為1。試想一個“不占空間“的變量如何被取位址、兩個不同的“空結構體”變量又如何得以區分呢,于是,“空結構體”變量也得被存儲,這樣編譯器也就隻能為其配置設定一個位元組的空間用于占位了。

例子:

struct S1  
{  
    char a;  
    int b;  
};  
sizeof(S1); //值為8,位元組對齊,在char之後會填充3個位元組。  
struct S2  
{  
     int b;  
     char a;  
};  
sizeof(S2); //值為8,位元組對齊,在char之後會填充3個位元組。  
struct S3  
{  
};  
sizeof(S3); //值為1,空結構體也占記憶體。 
           

3. 聯合體的sizeof

結構體在記憶體組織上市順序式的,聯合體則是重疊式,各成員共享一段記憶體;是以整個聯合體的sizeof也就是每個成員sizeof的最大值。

例子:

union u  
{  
    int a;  
    float b;  
    double c;  
    char d;  
};  
sizeof(u); //值為8  
           

4. 數組的sizeof

數組的sizeof值等于數組所占用的記憶體位元組數。

注意:1)當字元數組表示字元串時,其sizeof值将’/0’計算進去。

2)當數組為形參時,其sizeof值相當于指針的sizeof值。

例子1:

char a[10];  
 char n[] = "abc";   
 cout<<"char a[10]"<<sizeof(a)<<endl;//數組,值為10  
 cout<<"char n[] = /"abc/""<<sizeof(n)<<endl;//字元串數組,将'/0'計算進去,值為4  
           

例子2:

void func(char a[3])  
{  
    int c = sizeof(a); //c = 4,因為這裡a不在是數組類型,而是指針,相當于char *a。  
}  
void funcN(char b[])  
{  
    int cN = sizeof(b); //cN = 4,理由同上。  
}  
           

5. 指針的sizeof

指針是用來記錄另一個對象的位址,是以指針的記憶體大小當然就等于計算機内部位址總線的寬度。

在32位計算機中,一個指針變量的傳回值必定是4。

指針變量的sizeof值與指針所指的對象沒有任何關系。

例子:

char *b = "helloworld";  
char *c[10];  
double *d;  
int **e;  
void (*pf)();    
cout<<"char *b = /"helloworld/"     "<<sizeof(b)<<endl;//指針指向字元串,值為4  
cout<<"char *b                    "<<sizeof(*b)<<endl; //指針指向字元,值為1  
cout<<"double *d                  "<<sizeof(d)<<endl;//指針,值為4  
cout<<"double *d                  "<<sizeof(*d)<<endl;//指針指向浮點數,值為8  
cout<<"int **e                  "<<sizeof(e)<<endl;//指針指向指針,值為4  
cout<<"char *c[10]                "<<sizeof(c)<<endl;//指針數組,值為40  
cout<<"void (*pf)();              "<<sizeof(pf)<<endl;//函數指針,值為4  
           

6. 函數的sizeof

sizeof也可對一個函數調用求值,其結果是函數傳回值類型的大小,函數并不會被調用。

對函數求值的形式:sizeof(函數名(實參表))

注意:1)不可以對傳回值類型為空的函數求值。

2)不可以對函數名求值。

3)對有參數的函數,在用sizeof時,須寫上實參表。

例子:

#include <iostream>  
using namespace std;  
float FuncP(int a, float b)  
{  
     return a + b;  
}  
int FuncNP()  
{  
     return 3;  
}  
void Func()  
{  
}  
int main()  
{  
    cout<<sizeof(FuncP(3, 0.4))<<endl; //OK,值為4,sizeof(FuncP(3,0.4))相當于sizeof(float)  
    cout<<sizeof(FuncNP())<<endl; //OK,值為4,sizeof(FuncNP())相當于sizeof(int)  
    /*cout<<sizeof(Func())<<endl; //error,sizeof不能對傳回值為空類型的函數求值*/  
    /*cout<<sizeof(FuncNP)<<endl; //error,sizeof不能對函數名求值*/  
}   
           

參考:https://blog.csdn.net/sinat_20265495/article/details/51622990

繼續閱讀