news 2026/6/10 9:09:27

一文带你分清C++的定义,声明和初始化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一文带你分清C++的定义,声明和初始化

定义

变量的定义用于为变量分配存储空间,还可以为变量指定初始值。

1

2

3

4

intunits_sold;

doublesales_price, avg_price;

std::string title;

Sales_item curr_book;// class Sales_item

初始化

C++ 支持两种初始化变量的形式:复制初始化和直接初始化。复制初始化语法用等号(=),直接初始化则是把初始化式放在括号中。

1

2

intival(1024);// direct-initialization

intival = 1024;// copy-initialization

初始化不是赋值。初始化指创建变量并给它赋初始值,而赋值则是擦除对象的当前值并用新值代替。

当定义没有初始化式的变量时,系统有时候会帮我们初始化变量。

1.内置类型变量

(Built-in Types,即int,float,double,void,char,bool等。注意string是标准库定义的类型,不是内置类型)

在函数体外定义的变量都初始化成 0,在函数体里定义的内置类型变量不进行自动初始化。

2.类

类通过定义一个或多个构造函数来控制类对象的初始化。创建类类型的新对象,都要执行构造函数,保证每个对象的数据成员具有合适的初始值。

构造函数可以包含一个构造函数初始化列表,以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个数据成员后面跟一个放在圆括号中的初始化式。与任意的成员函数一样,构造函数可以定义在类的内部或外部。

构造函数初始化只在构造函数的定义中而不是声明中指定。

1

2

3

//将 isbn 成员初始化为 book 形参的值,将 units_sold 和 revenue 初始化为 0。

Sales_item::Sales_item(conststring &book):

isbn(book), units_sold(0), revenue(0.0) { }

如果没有提供初始化式,那么就会使用默认构造函数。如果类具有默认构造函数,那么就可以在定义该类的变量时不用显式地初始化变量。例如,string 类定义了默认构造函数来初始化 string 变量为空字符串。

1

2

string a;

cout <<"a: "<< a <<endl;

输出:

a:

此外,省略初始化列表在构造函数的函数体内对数据成员赋值是合法的。

1

2

3

4

5

6

Sales_item::Sales_item(conststring &book)

{

isbn = book;

units_sold = 0;

revenue = 0.0;

}

不管成员是否在构造函数初始化列表中显式初始化,类类型的数据成员总是在初始化阶段初始化。初始化发生在计算阶段开始之前。(也就是函数体执行以前)→ 这里似乎有些难以理解,通过后文的实例也许你能明白

在构造函数初始化列表中没有显式提及的每个成员,使用与初始化变量相同的规则来进行初始化。运行该类型的默认构造函数,来初始化类类型的数据成员。内置或复合类型的成员的初始值依赖于对象的作用域:在局部作用域中这些成员不被初始化,而在全局作用域中它们被初始化为 0。

未初始化的变量

局部作用域的内置类型变量将不被自动初始化,这可能导致其成为未初始化的变量。这是常见的程序错误,但编译器无法检测出所有未初始化变量的使用。→ 你肯定可以理解这可能导致的灾难性后果了(这竟然不可以运行,为什么呢?这竟然可以运行,为什么呢?.jpg)再稍微解释一下原因:问题出在未初始化的变量事实上都有一个值。编译器把该变量放到内存中的某个位置,而把这个位置的无论哪种位模式都当成是变量初始的状态。当被解释成整型值时,任何位模式都是合法的值——虽然这个值不可能是程序员想要的。因为这个值合法,所以使用它也不可能会导致程序崩溃。可能的结果是导致程序错误执行和/或错误计算。

声明

声明用于向程序表明变量的类型和名字。定义也是声明:当定义变量时我们声明了它的类型和名字。

可以通过使用extern关键字声明变量名而不定义它。extern 声明不是定义,也不分配存储空间。事实上,它只是说明变量定义在程序的其他地方。程序中变量可以声明多次,但只能定义一次。

1

2

externinti;// declares but does not define i

inti;// declares and defines i

只有当声明也是定义时,声明才可以有初始化式,因为只有定义才分配存储空间。初始化式必须要有存储空间来进行初始化。如果声明有初始化式,那么它可被当作是定义,即使声明标记为 extern:

1

externinti = 10;//defines i

在 C++ 语言中,变量必须且仅能定义一次,而且在使用变量之前必须定义或声明变量。

实例

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

#include <iostream>

#include <string>

usingnamespacestd;

//类x的声明

//如果这一部分放在main()函数后面,报错:error: 'x' was not declared in this scope

//在实际工程中,这部分声明将放在头文件(.h)中,而构造函数及成员函数的定义则放在.cpp文件中

classx{

public:

x(inta,intb, string c);

voidprint_data();

private:

//类数据成员的变量名最好在开头加一个字母m(即member)

intma;

intmb;

string mc;

};

intmain(){

inta1(2);//直接初始化

intb1 = 3;//复制初始化

string c1;//默认构造函数初始化string变量为空字符串

c1 ="dwkw";//赋值

x data(a1, b1, c1);//调用构造函数初始化

return0;

print_data();

}

//构造函数定义

x::x(inta,intb, string c):ma(a), mb(b), mc(c){}

//成员函数定义

voidx::print_data(){

cout <<"ma: "<< ma << endl;

cout <<"mb: "<< mb << endl;

cout <<"mc: "<< mc << endl;

}

输出:

ma: 2
mb: 3
mc: dwkw

声明时提供初值

如果在类的声明中就对数据成员提供初值,而不在初始化列表中提供,程序可以执行,输出ma的值为1。

1

2

3

4

5

6

7

8

9

10

11

classx{

public:

x(inta,intb, string c);

voidprint_data();

private:

intma =1;//声明时提供初值

intmb;

string mc;

};

//去掉初始化列表

x::x(inta,intb, string c):mb(b), mc(c){}

这一做法在早期版本不予支持,但从c++11就可以了。[2]

不过这破坏了类的抽象性,并不建议这样做。

查看c++版本的方法:[3]

1

cout << __cplusplus << endl;//输出c++版本

在构造函数内赋初值,而不用列表

前面提到省略初始化列表在构造函数的函数体内对数据成员赋值是合法的。

1

2

3

4

5

6

7

8

9

10

//去掉初始化列表,在构造函数体内赋值

//其它代码保持不变

x::x(inta,intb, 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

实际上我就没写初始化列表,但系统它就会在这里执行初始化。总之就会在执行构造函数体内的语句之前初始化(如果它可以自动初始化),即使根本没写初始化列表。→ 啧,我就像在说绕口令,希望你能明白我的意思

但是ma和mb都是局部作用域(我不确定类作用域是否是局部作用域,但从输出来看,ma不是0,所以应该没有能够初始化)的内置类型变量,不进行自动初始化;mc有默认构造函数,自动初始化为空字符串。而后,执行构造函数体内部的语句,将对ma和mb进行初始化(我想这里应该是初始化而不是赋值),对mc赋值。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 8:44:06

2026在线去水印工具推荐!免费在线去水印工具实测好用

日常刷短视频、浏览图文素材时&#xff0c;很多优质内容都会带有平台水印、作者logo、文字标注等印记&#xff0c;想要保存干净的素材用于个人收藏、学习参考&#xff0c;就需要用到靠谱的去水印工具。市面上去水印工具五花八门&#xff0c;付费软件操作繁琐、普通工具画质压缩…

作者头像 李华
网站建设 2026/6/10 8:42:58

248张512×512肺结节CT图+VOC标注+一键可视化脚本

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;直接可用的肺结节目标检测数据集&#xff0c;含248张512512像素RGB格式CT图像&#xff0c;全部标注为单一类别‘肺结节’&#xff0c;采用标准PASCAL VOC格式XML文件&#xff0c;严格区分train/test目录结构&am…

作者头像 李华
网站建设 2026/6/10 8:42:56

Web渗透测试实战复盘:避开误区、精准挖洞与安全防护思路

在网络安全攻防对抗愈发激烈的当下&#xff0c;Web渗透测试不再是单纯的技术炫技&#xff0c;而是企业风险管控的核心手段。不少入门从业者在实操中常陷入“只会工具扫描、不懂原理复盘、忽略风险边界”的误区&#xff0c;导致测试流于形式&#xff0c;无法发现深层高危漏洞。本…

作者头像 李华
网站建设 2026/6/10 8:42:00

【国奖论文】2026亚太杯中文赛ABC题解题思路+配套代码

2026年第十六届APMCM亚太地区数学建模竞赛&#xff08;中文赛项&#xff09;常见选题分析&#xff01;附优秀论文及赛题完整版优秀论文 通过网盘分享的文件&#xff1a;亚太杯赛前助攻资料领取 链接: https://pan.baidu.com/s/1GKj-nFXRxB0pEbCyneD0ww 提取码: 6666 --来自百…

作者头像 李华