C++ struct constructor
?????下面看看一道關于C++中筆試題:
// FileName:test.cpp
1:??#include <stdio.h>
2:??struct test
3:??{
4:???????test(int n){
5:???????????printf("test(%d)\n",n);
6:???????}
7:???????test(){
8:???????????printf("test()\n");
9:?????????}
10:??????void Fun(){
11:??????????printf("Fun()\n");
12:??????}
13:??};
14:??int main()
15:??{
16:??????test a(1);
17:??????a.Fun();
18:??????test b();
19:??????b.Fun();
20:??????return 0;
21:???}
????從編譯角度來思考下:
摘自csdn:?http://blog.csdn.net/fuadam/archive/2008/08/04/2766616.aspx
????最近才知道struct和class的靜態構造函數的觸發規則是不同的,不像class在第一次使用類的時候觸發靜態構造函數。如果只訪問struct實例的字段是不會觸發靜態構造函數調用的。通過測試發現當訪問靜態字段,struct本身的函數(靜態和實例)和帶參數的構造函數就會引起靜態構造函數的執行。而調用默認構造和未覆寫的基類虛函數是不會的。為什么呢?
????讓我們先來看看class和struct在調用構造函數時的區別。class使用newobj指令而struct使用initobj指令來構造對象。newobj在堆上申請一塊內存并調用相應的構造函數進行初始化,然后將對象地址返回給計算棧。initobj則是從本地變量表中載入已經分配出來的struct實例然后初始化struct的各字段。這個初始化過程是CLR內部執行的,而不像class編譯器會給class添加一個默認構造函數(這就是為什么struct不能給字段添加默認值的原因。但在類中如果給字段添加了默認值編譯器就會自動在構造函數中添加字段賦值操作)。如果給struct中定義了一個有參數的構造函數,那么系統就不會使用initobj指令,而是直接用call指令調用帶參數的構造函數。
????我們最常見最常用的調用函數的指令是call和callvirt。對于靜態函數使用call指令,對于class使用callvirt指令(不論class中的函數是不是虛的)。只有子類調用父類的函數的時候(避免遞歸調用)以及構造函數中(由編譯器添加保證父類字段被初始化)使用call指令。而對于struct我們發現只要調用的函數是struct本身定義的都是使用call指令。call和callvirt指令的差別在于,call會把調用的函數當作靜態函數看待,而不會關心調用當前函數時實例指針(this)是否為空。這就是struct調用函數時為什么都是call因為struct實例是不可能被置為null的。實際上class在調用非虛函數時實際上也是使用call的只是多做了一步驗證——this是否為空,讓我們來驗證一下。
總結
以上是生活随笔為你收集整理的C++ struct constructor的全部內容,希望文章能夠幫你解決所遇到的問題。