網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
定義
變量的定義用于為變量分配存儲(chǔ)空間,還可以為變量指定初始值。
int units_sold; double sales_price, avg_price; std::string title; Sales_item curr_book; // class Sales_item
初始化
C++ 支持兩種初始化變量的形式:復(fù)制初始化和直接初始化。復(fù)制初始化語(yǔ)法用等號(hào)(=),直接初始化則是把初始化式放在括號(hào)中。
int ival(1024); // direct-initialization int ival = 1024; // copy-initialization
初始化不是賦值。初始化指創(chuàng)建變量并給它賦初始值,而賦值則是擦除對(duì)象的當(dāng)前值并用新值代替。
當(dāng)定義沒有初始化式的變量時(shí),系統(tǒng)有時(shí)候會(huì)幫我們初始化變量。
1.內(nèi)置類型變量
(Built-in Types,即int,float,double,void,char,bool等。注意string是標(biāo)準(zhǔn)庫(kù)定義的類型,不是內(nèi)置類型)
在函數(shù)體外定義的變量都初始化成 0,在函數(shù)體里定義的內(nèi)置類型變量不進(jìn)行自動(dòng)初始化。
2.類
類通過定義一個(gè)或多個(gè)構(gòu)造函數(shù)來(lái)控制類對(duì)象的初始化。創(chuàng)建類類型的新對(duì)象,都要執(zhí)行構(gòu)造函數(shù),保證每個(gè)對(duì)象的數(shù)據(jù)成員具有合適的初始值。
構(gòu)造函數(shù)可以包含一個(gè)構(gòu)造函數(shù)初始化列表,以一個(gè)冒號(hào)開始,接著是一個(gè)以逗號(hào)分隔的數(shù)據(jù)成員列表,每個(gè)數(shù)據(jù)成員后面跟一個(gè)放在圓括號(hào)中的初始化式。與任意的成員函數(shù)一樣,構(gòu)造函數(shù)可以定義在類的內(nèi)部或外部。
構(gòu)造函數(shù)初始化只在構(gòu)造函數(shù)的定義中而不是聲明中指定。
//將 isbn 成員初始化為 book 形參的值,將 units_sold 和 revenue 初始化為 0。 Sales_item::Sales_item(const string &book): isbn(book), units_sold(0), revenue(0.0) { }
如果沒有提供初始化式,那么就會(huì)使用默認(rèn)構(gòu)造函數(shù)。如果類具有默認(rèn)構(gòu)造函數(shù),那么就可以在定義該類的變量時(shí)不用顯式地初始化變量。例如,string 類定義了默認(rèn)構(gòu)造函數(shù)來(lái)初始化 string 變量為空字符串。
string a; cout << "a: " << a <
輸出:
a:?
此外,省略初始化列表在構(gòu)造函數(shù)的函數(shù)體內(nèi)對(duì)數(shù)據(jù)成員賦值是合法的。
Sales_item::Sales_item(const string &book) { isbn = book; units_sold = 0; revenue = 0.0; }
不管成員是否在構(gòu)造函數(shù)初始化列表中顯式初始化,類類型的數(shù)據(jù)成員總是在初始化階段初始化。初始化發(fā)生在計(jì)算階段開始之前。(也就是函數(shù)體執(zhí)行以前)→ 這里似乎有些難以理解,通過后文的實(shí)例也許你能明白
在構(gòu)造函數(shù)初始化列表中沒有顯式提及的每個(gè)成員,使用與初始化變量相同的規(guī)則來(lái)進(jìn)行初始化。運(yùn)行該類型的默認(rèn)構(gòu)造函數(shù),來(lái)初始化類類型的數(shù)據(jù)成員。內(nèi)置或復(fù)合類型的成員的初始值依賴于對(duì)象的作用域:在局部作用域中這些成員不被初始化,而在全局作用域中它們被初始化為 0。
未初始化的變量
局部作用域的內(nèi)置類型變量將不被自動(dòng)初始化,這可能導(dǎo)致其成為未初始化的變量。這是常見的程序錯(cuò)誤,但編譯器無(wú)法檢測(cè)出所有未初始化變量的使用。→ 你肯定可以理解這可能導(dǎo)致的災(zāi)難性后果了(這竟然不可以運(yùn)行,為什么呢?這竟然可以運(yùn)行,為什么呢?.jpg)再稍微解釋一下原因:?jiǎn)栴}出在未初始化的變量事實(shí)上都有一個(gè)值。編譯器把該變量放到內(nèi)存中的某個(gè)位置,而把這個(gè)位置的無(wú)論哪種位模式都當(dāng)成是變量初始的狀態(tài)。當(dāng)被解釋成整型值時(shí),任何位模式都是合法的值——雖然這個(gè)值不可能是程序員想要的。因?yàn)檫@個(gè)值合法,所以使用它也不可能會(huì)導(dǎo)致程序崩潰。可能的結(jié)果是導(dǎo)致程序錯(cuò)誤執(zhí)行和/或錯(cuò)誤計(jì)算。
聲明
聲明用于向程序表明變量的類型和名字。定義也是聲明:當(dāng)定義變量時(shí)我們聲明了它的類型和名字。
可以通過使用extern關(guān)鍵字聲明變量名而不定義它。extern 聲明不是定義,也不分配存儲(chǔ)空間。事實(shí)上,它只是說明變量定義在程序的其他地方。程序中變量可以聲明多次,但只能定義一次。
extern int i; // declares but does not define i int i; // declares and defines i
只有當(dāng)聲明也是定義時(shí),聲明才可以有初始化式,因?yàn)橹挥卸x才分配存儲(chǔ)空間。初始化式必須要有存儲(chǔ)空間來(lái)進(jìn)行初始化。如果聲明有初始化式,那么它可被當(dāng)作是定義,即使聲明標(biāo)記為 extern:
extern int i = 10; //defines i
在 C++ 語(yǔ)言中,變量必須且僅能定義一次,而且在使用變量之前必須定義或聲明變量。
實(shí)例
#include#include using namespace std; //類x的聲明 //如果這一部分放在main()函數(shù)后面,報(bào)錯(cuò):error: 'x' was not declared in this scope //在實(shí)際工程中,這部分聲明將放在頭文件(.h)中,而構(gòu)造函數(shù)及成員函數(shù)的定義則放在.cpp文件中 class x{ public: x(int a, int b, string c); void print_data(); private: //類數(shù)據(jù)成員的變量名最好在開頭加一個(gè)字母m(即member) int ma; int mb; string mc; }; int main(){ int a1(2); //直接初始化 int b1 = 3; //復(fù)制初始化 string c1; //默認(rèn)構(gòu)造函數(shù)初始化string變量為空字符串 c1 = "dwkw"; //賦值 x data(a1, b1, c1); //調(diào)用構(gòu)造函數(shù)初始化 return 0; print_data(); } //構(gòu)造函數(shù)定義 x::x(int a, int b, string c):ma(a), mb(b), mc(c){} //成員函數(shù)定義 void x::print_data(){ cout << "ma: " << ma << endl; cout << "mb: " << mb << endl; cout << "mc: " << mc << endl; }
輸出:
ma: 2
mb: 3
mc: dwkw
聲明時(shí)提供初值
如果在類的聲明中就對(duì)數(shù)據(jù)成員提供初值,而不在初始化列表中提供,程序可以執(zhí)行,輸出ma的值為1。
class x{ public: x(int a, int b, string c); void print_data(); private: int ma = 1; //聲明時(shí)提供初值 int mb; string mc; }; //去掉初始化列表 x::x(int a, int b, string c):mb(b), mc(c){}
這一做法在早期版本不予支持,但從c++11就可以了。[2]
不過這破壞了類的抽象性,并不建議這樣做。
查看c++版本的方法:[3]
cout << __cplusplus << endl; //輸出c++版本
在構(gòu)造函數(shù)內(nèi)賦初值,而不用列表
前面提到省略初始化列表在構(gòu)造函數(shù)的函數(shù)體內(nèi)對(duì)數(shù)據(jù)成員賦值是合法的。
//去掉初始化列表,在構(gòu)造函數(shù)體內(nèi)賦值 //其它代碼保持不變 x::x(int a, int b, string c){ cout << "賦值前: " << endl; print_data(); cout << "賦值后: " << endl; ma = 4; mb = 5; mc = "ser"; }
輸出:
賦值前:?
ma: 4199744
mb: 0
mc:?
賦值后:?
ma: 4
mb: 5
mc: ser
實(shí)際上我就沒寫初始化列表,但系統(tǒng)它就會(huì)在這里執(zhí)行初始化。總之就會(huì)在執(zhí)行構(gòu)造函數(shù)體內(nèi)的語(yǔ)句之前初始化(如果它可以自動(dòng)初始化),即使根本沒寫初始化列表。→ 嘖,我就像在說繞口令,希望你能明白我的意思
但是ma和mb都是局部作用域(我不確定類作用域是否是局部作用域,但從輸出來(lái)看,ma不是0,所以應(yīng)該沒有能夠初始化)的內(nèi)置類型變量,不進(jìn)行自動(dòng)初始化;mc有默認(rèn)構(gòu)造函數(shù),自動(dòng)初始化為空字符串。
而后,執(zhí)行構(gòu)造函數(shù)體內(nèi)部的語(yǔ)句,將對(duì)ma和mb進(jìn)行初始化(我想這里應(yīng)該是初始化而不是賦值),對(duì)mc賦值。
總結(jié)
原文鏈接:https://blog.csdn.net/qq_44920947/article/details/123216283
相關(guān)推薦
- 2022-09-12 PyQt轉(zhuǎn)換路徑中的斜杠(斜杠(/)與反斜杠(\)轉(zhuǎn)換)_python
- 2023-02-12 Python利用物理引擎Pymunk編寫一個(gè)解壓小游戲_python
- 2022-09-07 C語(yǔ)言函數(shù)調(diào)用約定和返回值詳情_C 語(yǔ)言
- 2022-09-10 Go語(yǔ)言的反射機(jī)制詳解_Golang
- 2022-07-11 Could not transfer artifact org.springframework.bo
- 2022-12-13 C++?Boost?Format超詳細(xì)講解_C 語(yǔ)言
- 2022-09-05 Golang中的Interface詳解_Golang
- 2022-07-19 Android通過交互實(shí)現(xiàn)貝塞爾曲線的繪制_Android
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支