程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++初始化列表進修

C++初始化列表進修

編輯:關於C++

C++初始化列表進修。本站提示廣大學習愛好者:(C++初始化列表進修)文章只能為提供參考,不一定能成為您想要的結果。以下是C++初始化列表進修正文


何謂初始化列表
與其他函數分歧,結構函數除著名字,參數列表和函數體以外,還可以有初始化列表,初始化列表以冒號開首,後跟一系列以逗號分隔的初始化字段。在C++中,struct和class的獨一差別是默許的克拜訪性分歧,而這裡我們不斟酌拜訪性的成績,所以上面的代碼都以struct來演示。

struct foo
{
    string name ;
    int id ;
    foo(string s, int i):name(s), id(i){} ; // 初始化列表
};

結構函數的兩個履行階段
結構函數的履行可以分紅兩個階段,初始化階段和盤算階段,初始化階段先於盤算階段。

初始化階段
一切類類型(class type)的成員都邑在初始化階段初始化,即便該成員沒有湧現在結構函數的初始化列表中。

盤算階段
普通用於履行結構函數體內的賦值操作,上面的代碼界說兩個構造體,個中Test1有結構函數,拷貝結構函數及賦值運算符,為的是便利檢查成果。Test2是個測試類,它以Test1的對象為成員,我們看一下Test2的結構函數是怎樣樣履行的。

struct Test1
{
    Test1() // 無參結構函數
    {
        cout << "Construct Test1" << endl ;
    }

    Test1(const Test1& t1) // 拷貝結構函數
    {
        cout << "Copy constructor for Test1" << endl ;
        this->a = t1.a ;
    }

    Test1& operator = (const Test1& t1) // 賦值運算符
    {
        cout << "assignment for Test1" << endl ;
        this->a = t1.a ;
        return *this;
    }

    int a ;
};

struct Test2
{
    Test1 test1 ;
    Test2(Test1 &t1)
    {
        test1 = t1 ;
    }
};

挪用代碼

Test1 t1 ;
Test2 t2(t1) ;

輸入



說明一下,第一行輸入對應挪用代碼中第一行,結構一個Test1對象。第二行輸入對應Test2結構函數中的代碼,用默許的結構函數初始化對象test1,這就是所謂的初始化階段。第三行輸入對應Test1的賦值運算符,對test1履行賦值操作,這就是所謂的盤算階段。

為何應用初始化列表
初始化類的成員有兩種方法,一是應用初始化列表,二是在結構函數體內停止賦值操作。應用初始化列表重要是基於機能成績,關於內置類型,如int, float等,應用初始化類表和在結構函數體內初始化差異不是很年夜,然則關於類類型來講,最好應用初始化列表,為何呢?由下面的測試可知,應用初始化列表少了一次挪用默許結構函數的進程,這關於數據密集型的類來講,長短常高效的。異樣看下面的例子,我們應用初始化列表來完成Test2的結構函數

struct Test2
{
    Test1 test1 ;
    Test2(Test1 &t1):test1(t1){}
}

應用異樣的挪用代碼,輸入成果以下。

第一行輸入對應 挪用代碼的第一行。第二行輸入對應Test2的初始化列表,直接挪用拷貝結構函數初始化test1,省去了挪用默許結構函數的進程。所以一個好的准繩是,能應用初始化列表的時刻盡可能應用初始化列表。

哪些器械必需放在初始化列表中
除機能成績以外,有些時場所初始化列表是弗成或缺的,以下幾種情形時必需應用初始化列表

常量成員,由於常量只能初始化不克不及賦值,所以必需放在初始化列內外面
援用類型,援用必需在界說的時刻初始化,而且不克不及從新賦值,所以也要寫在初始化列內外面
沒有默許結構函數的類類型,由於應用初始化列表可以不用挪用默許結構函數來初始化,而是直接挪用拷貝結構函數初始化。
關於沒有默許結構函數的類,我們看一個例子。

struct Test1
{
    Test1(int a):i(a){}
    int i ;
};

struct Test2
{
    Test1 test1 ;
    Test2(Test1 &t1)
    {
        test1 = t1 ;
    }
};

以上代碼沒法經由過程編譯,由於Test2的結構函數中test1 = t1這一行現實上分紅兩步履行。

1. 挪用Test1的默許結構函數來初始化test1
2. 挪用Test1的賦值運算符給test1賦值

然則因為Test1沒有默許的結構函數,所謂第一步沒法履行,故而編譯毛病。准確的代碼以下,應用初始化列表取代賦值操作。

struct Test2
{
    Test1 test1 ;
    Test2(Test1 &t1):test1(t1){}
}

成員變量的初始化次序
成員是依照他們在類中湧現的次序停止初始化的,而不是依照他們在初始化列表湧現的次序初始化的,看代碼。

struct foo
{
    int i ;
    int j ;
    foo(int x):i(x), j(i){}; // ok, 先初始化i,後初始化j
};

再看上面的代碼

struct foo
{
    int i ;
    int j ;
    foo(int x):j(x), i(j){} // i值不決義
};

這裡i的值是不決義的由於固然j在初始化列內外面湧現在i後面,然則i先於j界說,所以先初始化i,但i由j初始化,此時j還沒有初始化,所以招致i的值不決義。所以,一個好的習氣是,依照成員界說的次序停止初始化。

System.getProperties(); //取得體系屬性集 String osName = props.getProperty("os.name"); //操作體系稱號 String osArch = props.getProperty("os.arch"); //操作體系構架 String osVersion = props.getProperty("os.version"); //操作體系版本

   
6.一些經常使用的信息取得方法整頓

java.version    Java 運轉時情況版本 
java.vendor     Java 運轉時情況供給商 
java.vendor.url     Java 供給商的 URL 
java.home   Java 裝置目次 
java.vm.specification.version   Java 虛擬機標准版本 
java.vm.specification.vendor    Java 虛擬機標准供給商 
java.vm.specification.name  Java 虛擬機標准稱號 
java.vm.version     Java 虛擬機完成版本 
java.vm.vendor  Java 虛擬機完成供給商 
java.vm.name    Java 虛擬機完成稱號 
java.specification.version  Java 運轉時情況標准版本 
java.specification.vendor   Java 運轉時情況標准供給商 
java.specification.name     Java 運轉時情況標准稱號 
java.class.version  Java 類格局版本號 
java.class.path     Java 類途徑 
java.library.path   加載庫時搜刮的途徑列表 
java.io.tmpdir  默許的暫時文件途徑 
java.compiler   要應用的 JIT 編譯器的稱號 
java.ext.dirs   一個或多個擴大目次的途徑 
os.name     操作體系的稱號 
os.arch     操作體系的架構 
os.version  操作體系的版本 
file.separator  文件分隔符(在 UNIX 體系中是“/”) 
path.separator  途徑分隔符(在 UNIX 體系中是“:”) 
line.separator  行分隔符(在 UNIX 體系中是“/n”) 
user.name   用戶的賬戶稱號 
user.home   用戶的主目次 
user.dir    用戶確當前任務目次 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved