国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C/C++ - 成員初始化列表與構造函數體中的區別詳細解析

成員初始化列表與構造函數體中的區別詳細解析

2021-01-03 16:01C++教程網 C/C++

無論是在構造函數初始化列表中初始化成員,還是在構造函數體中對它們賦值,最終結果是相同的。不同之處在于,使用構造函數初始化列表的版本初始化數據成員,沒有定義初始化列表的構造函數版本在構造函數體中對數據成員

論壇中回答一個別人問題

C++ Primer中在講構造函數初始化列表的時候有這么一段話:
無論是在構造函數初始化列表中初始化成員,還是在構造函數體中對它們賦值,最終結果是相同的。不同之處在于,使用構造函數初始化列表的版本初始化數據成員,沒有定義初始化列表的構造函數版本在構造函數體中對數據成員賦值。

請問這里的初始化數據成員與對數據成員賦值的含義是什么?有什么區別?

我知道在數據成員有默認構造函數時是有不同的,但對其他類型的成員呢?其他類型成員的初始化和賦值有區別嗎?
=========================================================================
是這個意思:
首先把數據成員按類型分類
1。內置數據類型,復合類型(指針,引用)
2。用戶定義類型(類類型)

分情況說明:
對于類型1,在成員初始化列表和構造函數體內進行,在性能和結果上都是一樣的
對于類型2,結果上相同,但是性能上存在很大的差別

因為類類型的數據成員對象在進入函數體是已經構造完成,也就是說在成員初始化列表處進行構造對象的工作,這是調用一個構造函數,在進入函數體之后,進行的是 對已經構造好的類對象的賦值,又調用個拷貝賦值操作符才能完成(如果并未提供,則使用編譯器提供的默認按成員賦值行為)

舉個例說明
class A;
class B
{public:
B(){a = 3;}
private:
A a;
}

class A
{public:
A(){}
A(int){value = 3;}
int value;
}

像上面,我們使a對象的value為3,調用一個A的構造函數+一個默認拷貝賦值符,才達到目的
B::B():a(3){}
像這樣,只調用了一個構造函數就達到了所需的對象啦,所以性能好的

轉載他人一篇

我的問題是關于初始化C++類成員的。我見過許多這樣的代碼(包括在你的欄目中也見到過):

復制代碼 代碼如下:


CSomeClass::CSomeClass()

 

{

    x=0;

    y=1;

}


而在別的什么地方則寫成下面的樣子:

復制代碼 代碼如下:


CSomeClass::CSomeClass() : x(0), y(1)

 

{

}


我的一些程序員朋友說第二種方法比較好,但他們都不知道為什么是這樣。你能告訴我這兩種類成員初始化方法的區別嗎?

 

回答

從技術上說,你的程序員朋友是對的,但是在大多數情況下,兩者實際上沒有區別。有兩個原因使得我們選擇第二種語法,它被稱為成員初始化列表:一個原因是必須的,另一個只是出于效率考慮。

讓我們先看一下第一個原因——必要性。設想你有一個類成員,它本身是一個類或者結構,而且只有一個帶一個參數的構造函數。

復制代碼 代碼如下:


class CMember {

 

public:

    CMember(int x) { ... }

};


因為Cmember有一個顯式聲明的構造函數,編譯器不產生一個缺省構造函數(不帶參數),所以沒有一個整數就無法創建Cmember的一個實例。

 

CMember* pm = new CMember;        // Error!!
CMember* pm = new CMember(2);     // OK

如果Cmember是另一個類的成員,你怎樣初始化它呢?你必須使用成員初始化列表。

復制代碼 代碼如下:


class CMyClass {

 

    CMember m_member;

public:

    CMyClass();

};

//必須使用成員初始化列表

CMyClass::CMyClass() : m_member(2)

{

•••

}


沒有其它辦法將參數傳遞給m_member,如果成員是一個常量對象或者引用也是一樣。根據C++的規則,常量對象和引用不能被賦值,它們只能被初始化。

 

第二個原因是出于效率考慮,當成員類具有一個缺省的構造函數和一個賦值操作符時。MFC的Cstring提供了一個完美的例子。假定你有一個類CmyClass具有一個Cstring類型的成員m_str,你想把它初始化為"yada yada."。你有兩種選擇:

復制代碼 代碼如下:


CMyClass::CMyClass() {

 

    // 使用賦值操作符

    // CString::operator=(LPCTSTR);

    m_str = _T("yada yada");

}

//使用類成員列表

// and constructor CString::CString(LPCTSTR)

CMyClass::CMyClass() : m_str(_T("yada yada"))

{

}


在 它們之間有什么不同嗎?是的。編譯器總是確保所有成員對象在構造函數體執行之前初始化,因此在第一個例子中編譯的代碼將調用CString:: Cstring來初始化m_str,這在控制到達賦值語句前完成。在第二個例子中編譯器產生一個對CString:: CString(LPCTSTR)的調用并將"yada yada"傳遞給這個函數。結果是在第一個例子中調用了兩個Cstring函數(構造函數和賦值操作符),而在第二個例子中只調用了一個函數。在 Cstring的例子里這是無所謂的,因為缺省構造函數是內聯的,Cstring只是在需要時為字符串分配內存(即,當你實際賦值時)。但是,一般而言, 重復的函數調用是浪費資源的,尤其是當構造函數和賦值操作符分配內存的時候。在一些大的類里面,你可能擁有一個構造函數和一個賦值操作符都要調用同一個負 責分配大量內存空間的Init函數。在這種情況下,你必須使用初始化列表,以避免不要的分配兩次內存。在內部類型如ints或者longs或者其它沒有構 造函數的類型下,在初始化列表和在構造函數體內賦值這兩種方法沒有性能上的差別。不管用那一種方法,都只會有一次賦值發生。有些程序員說你應該總是用初始 化列表以保持良好習慣,但我從沒有發現根據需要在這兩種方法之間轉換有什么困難。在編程風格上,我傾向于在主體中使用賦值,因為有更多的空間用來格式化和 添加注釋,你可以寫出這樣的語句:x=y=z=0;

 

或者memset(this,0,sizeof(this));

注意第二個片斷絕對是非面向對象的。

當我考慮初始化列表的問題時,有一個奇怪的特性我應該警告你,它是關于C++初始化類成員的,它們是按照聲明的順序初始化的,而不是按照出現在初始化列表中的順序。

復制代碼 代碼如下:


class CMyClass {

 

    CMyClass(int x, int y);

    int m_x;

    int m_y;

};

CMyClass::CMyClass(int i) : m_y(i), m_x(m_y)

{

}


你可能以為上面的代碼將會首先做m_y=I,然后做m_x=m_y,最后它們有相同的值。但是編譯器先初始化m_x,然后是m_y,,因為它們是按這樣的順 序聲明的。結果是m_x將有一個不可預測的值。我的例子設計來說明這一點,然而這種bug會更加自然的出現。有兩種方法避免它,一個是總是按照你希望它們 被初始化的順序聲明成員,第二個是,如果你決定使用初始化列表,總是按照它們聲明的順序羅列這些成員。這將有助于消除混淆。

延伸 · 閱讀

精彩推薦
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下...

    青山的青6062022-01-04
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內存中的數據都是暫時的,當程序結束時,它們都將丟失,為了永久性的保存大量的數據,C語言提供了對文件的操作,這篇文章主要給大家介紹了關于C語言中文件...

    針眼_6702022-01-24
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數使用

    詳解c語言中的 strcpy和strncpy字符串函數使用

    strcpy 和strcnpy函數是字符串復制函數。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
  • C/C++學習C++編程的必備軟件

    學習C++編程的必備軟件

    本文給大家分享的是作者在學習使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
  • C/C++c++ 單線程實現同時監聽多個端口

    c++ 單線程實現同時監聽多個端口

    這篇文章主要介紹了c++ 單線程實現同時監聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
  • C/C++C語言實現電腦關機程序

    C語言實現電腦關機程序

    這篇文章主要為大家詳細介紹了C語言實現電腦關機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
  • C/C++C/C++經典實例之模擬計算器示例代碼

    C/C++經典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關于C/C++經典實例之模擬計算器的相關資料,文中通過示...

    jia150610152021-06-07
  • C/C++深入理解goto語句的替代實現方式分析

    深入理解goto語句的替代實現方式分析

    本篇文章是對goto語句的替代實現方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網7342020-12-03
主站蜘蛛池模板: 亚洲综合国产 | 中文字幕免费看 | 国产精品美女久久久久久免费 | 日韩av一区在线 | 在线成人 | aaa级大片| 欧洲精品码一区二区三区免费看 | 五月婷婷激情网 | 在线视频一区二区三区 | 欧美亚洲在线 | 精品www| 深夜网址 | 成人av在线播放 | 成人精品鲁一区一区二区 | 99精品欧美一区二区三区 | 免费不卡视频 | 日日爱视频 | 欧美一区二区三区不卡 | 日韩欧美中文字幕在线视频 | 免费在线看a | 99亚洲精品 | 日韩一区二区三区在线观看 | 国产日韩高清在线 | 久久成人高清 | 国产福利二区 | 国产精品爱久久久久久久 | 国产一区在线免费观看 | 亚洲综合视频 | 成人天堂666| 一级片在线观看 | 日韩在线欧美 | 欧美午夜一区二区福利视频 | 久久国产精品无码网站 | 国产精品美女久久久久久久久久久 | 精品国产欧美一区二区三区成人 | 99热新 | 色片在线观看 | 精品少妇一区二区三区 | 久久成人免费视频 | 成人亚洲欧美 | 成人va在线观看 |