定义变量的定义用于为变量分配存储空间还可以为变量指定初始值。1234intunits_sold;doublesales_price, avg_price;std::string title;Sales_item curr_book;// class Sales_item初始化C 支持两种初始化变量的形式复制初始化和直接初始化。复制初始化语法用等号直接初始化则是把初始化式放在括号中。12intival(1024);// direct-initializationintival 1024;// copy-initialization初始化不是赋值。初始化指创建变量并给它赋初始值而赋值则是擦除对象的当前值并用新值代替。当定义没有初始化式的变量时系统有时候会帮我们初始化变量。1.内置类型变量Built-in Types即intfloatdoublevoidcharbool等。注意string是标准库定义的类型不是内置类型在函数体外定义的变量都初始化成 0在函数体里定义的内置类型变量不进行自动初始化。2.类类通过定义一个或多个构造函数来控制类对象的初始化。创建类类型的新对象都要执行构造函数保证每个对象的数据成员具有合适的初始值。构造函数可以包含一个构造函数初始化列表以一个冒号开始接着是一个以逗号分隔的数据成员列表每个数据成员后面跟一个放在圆括号中的初始化式。与任意的成员函数一样构造函数可以定义在类的内部或外部。构造函数初始化只在构造函数的定义中而不是声明中指定。123//将 isbn 成员初始化为 book 形参的值将 units_sold 和 revenue 初始化为 0。Sales_item::Sales_item(conststring book):isbn(book), units_sold(0), revenue(0.0) { }如果没有提供初始化式那么就会使用默认构造函数。如果类具有默认构造函数那么就可以在定义该类的变量时不用显式地初始化变量。例如string 类定义了默认构造函数来初始化 string 变量为空字符串。12string a;cout a: a endl;输出a:此外省略初始化列表在构造函数的函数体内对数据成员赋值是合法的。123456Sales_item::Sales_item(conststring book){isbn book;units_sold 0;revenue 0.0;}不管成员是否在构造函数初始化列表中显式初始化类类型的数据成员总是在初始化阶段初始化。初始化发生在计算阶段开始之前。也就是函数体执行以前→ 这里似乎有些难以理解通过后文的实例也许你能明白在构造函数初始化列表中没有显式提及的每个成员使用与初始化变量相同的规则来进行初始化。运行该类型的默认构造函数来初始化类类型的数据成员。内置或复合类型的成员的初始值依赖于对象的作用域在局部作用域中这些成员不被初始化而在全局作用域中它们被初始化为 0。未初始化的变量局部作用域的内置类型变量将不被自动初始化这可能导致其成为未初始化的变量。这是常见的程序错误但编译器无法检测出所有未初始化变量的使用。→ 你肯定可以理解这可能导致的灾难性后果了这竟然不可以运行为什么呢这竟然可以运行为什么呢.jpg再稍微解释一下原因问题出在未初始化的变量事实上都有一个值。编译器把该变量放到内存中的某个位置而把这个位置的无论哪种位模式都当成是变量初始的状态。当被解释成整型值时任何位模式都是合法的值——虽然这个值不可能是程序员想要的。因为这个值合法所以使用它也不可能会导致程序崩溃。可能的结果是导致程序错误执行和/或错误计算。声明声明用于向程序表明变量的类型和名字。定义也是声明当定义变量时我们声明了它的类型和名字。可以通过使用extern关键字声明变量名而不定义它。extern 声明不是定义也不分配存储空间。事实上它只是说明变量定义在程序的其他地方。程序中变量可以声明多次但只能定义一次。12externinti;// declares but does not define iinti;// declares and defines i只有当声明也是定义时声明才可以有初始化式因为只有定义才分配存储空间。初始化式必须要有存储空间来进行初始化。如果声明有初始化式那么它可被当作是定义即使声明标记为 extern1externinti 10;//defines i在 C 语言中变量必须且仅能定义一次而且在使用变量之前必须定义或声明变量。实例12345678910111213141516171819202122232425262728293031323334353637#include iostream#include stringusingnamespacestd;//类x的声明//如果这一部分放在main()函数后面报错error: x was not declared in this scope//在实际工程中这部分声明将放在头文件.h中而构造函数及成员函数的定义则放在.cpp文件中classx{public:x(inta,intb, string c);voidprint_data();private://类数据成员的变量名最好在开头加一个字母m即memberintma;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: 2mb: 3mc: dwkw声明时提供初值如果在类的声明中就对数据成员提供初值而不在初始化列表中提供程序可以执行输出ma的值为1。1234567891011classx{public:x(inta,intb, string c);voidprint_data();private:intma 1;//声明时提供初值intmb;string mc;};//去掉初始化列表x::x(inta,intb, string c):mb(b), mc(c){}这一做法在早期版本不予支持但从c11就可以了。[2]不过这破坏了类的抽象性并不建议这样做。查看c版本的方法[3]1cout __cplusplus endl;//输出c版本在构造函数内赋初值而不用列表前面提到省略初始化列表在构造函数的函数体内对数据成员赋值是合法的。12345678910//去掉初始化列表在构造函数体内赋值//其它代码保持不变x::x(inta,intb, string c){cout 赋值前: endl;print_data();cout 赋值后: endl;ma 4;mb 5;mc ser;}输出赋值前:ma: 4199744mb: 0mc:赋值后:ma: 4mb: 5mc: ser实际上我就没写初始化列表但系统它就会在这里执行初始化。总之就会在执行构造函数体内的语句之前初始化如果它可以自动初始化即使根本没写初始化列表。→ 啧我就像在说绕口令希望你能明白我的意思但是ma和mb都是局部作用域我不确定类作用域是否是局部作用域但从输出来看ma不是0所以应该没有能够初始化的内置类型变量不进行自动初始化mc有默认构造函数自动初始化为空字符串。而后执行构造函数体内部的语句将对ma和mb进行初始化我想这里应该是初始化而不是赋值对mc赋值。
一文带你分清C++的定义,声明和初始化
发布时间:2026/6/10 9:09:35
定义变量的定义用于为变量分配存储空间还可以为变量指定初始值。1234intunits_sold;doublesales_price, avg_price;std::string title;Sales_item curr_book;// class Sales_item初始化C 支持两种初始化变量的形式复制初始化和直接初始化。复制初始化语法用等号直接初始化则是把初始化式放在括号中。12intival(1024);// direct-initializationintival 1024;// copy-initialization初始化不是赋值。初始化指创建变量并给它赋初始值而赋值则是擦除对象的当前值并用新值代替。当定义没有初始化式的变量时系统有时候会帮我们初始化变量。1.内置类型变量Built-in Types即intfloatdoublevoidcharbool等。注意string是标准库定义的类型不是内置类型在函数体外定义的变量都初始化成 0在函数体里定义的内置类型变量不进行自动初始化。2.类类通过定义一个或多个构造函数来控制类对象的初始化。创建类类型的新对象都要执行构造函数保证每个对象的数据成员具有合适的初始值。构造函数可以包含一个构造函数初始化列表以一个冒号开始接着是一个以逗号分隔的数据成员列表每个数据成员后面跟一个放在圆括号中的初始化式。与任意的成员函数一样构造函数可以定义在类的内部或外部。构造函数初始化只在构造函数的定义中而不是声明中指定。123//将 isbn 成员初始化为 book 形参的值将 units_sold 和 revenue 初始化为 0。Sales_item::Sales_item(conststring book):isbn(book), units_sold(0), revenue(0.0) { }如果没有提供初始化式那么就会使用默认构造函数。如果类具有默认构造函数那么就可以在定义该类的变量时不用显式地初始化变量。例如string 类定义了默认构造函数来初始化 string 变量为空字符串。12string a;cout a: a endl;输出a:此外省略初始化列表在构造函数的函数体内对数据成员赋值是合法的。123456Sales_item::Sales_item(conststring book){isbn book;units_sold 0;revenue 0.0;}不管成员是否在构造函数初始化列表中显式初始化类类型的数据成员总是在初始化阶段初始化。初始化发生在计算阶段开始之前。也就是函数体执行以前→ 这里似乎有些难以理解通过后文的实例也许你能明白在构造函数初始化列表中没有显式提及的每个成员使用与初始化变量相同的规则来进行初始化。运行该类型的默认构造函数来初始化类类型的数据成员。内置或复合类型的成员的初始值依赖于对象的作用域在局部作用域中这些成员不被初始化而在全局作用域中它们被初始化为 0。未初始化的变量局部作用域的内置类型变量将不被自动初始化这可能导致其成为未初始化的变量。这是常见的程序错误但编译器无法检测出所有未初始化变量的使用。→ 你肯定可以理解这可能导致的灾难性后果了这竟然不可以运行为什么呢这竟然可以运行为什么呢.jpg再稍微解释一下原因问题出在未初始化的变量事实上都有一个值。编译器把该变量放到内存中的某个位置而把这个位置的无论哪种位模式都当成是变量初始的状态。当被解释成整型值时任何位模式都是合法的值——虽然这个值不可能是程序员想要的。因为这个值合法所以使用它也不可能会导致程序崩溃。可能的结果是导致程序错误执行和/或错误计算。声明声明用于向程序表明变量的类型和名字。定义也是声明当定义变量时我们声明了它的类型和名字。可以通过使用extern关键字声明变量名而不定义它。extern 声明不是定义也不分配存储空间。事实上它只是说明变量定义在程序的其他地方。程序中变量可以声明多次但只能定义一次。12externinti;// declares but does not define iinti;// declares and defines i只有当声明也是定义时声明才可以有初始化式因为只有定义才分配存储空间。初始化式必须要有存储空间来进行初始化。如果声明有初始化式那么它可被当作是定义即使声明标记为 extern1externinti 10;//defines i在 C 语言中变量必须且仅能定义一次而且在使用变量之前必须定义或声明变量。实例12345678910111213141516171819202122232425262728293031323334353637#include iostream#include stringusingnamespacestd;//类x的声明//如果这一部分放在main()函数后面报错error: x was not declared in this scope//在实际工程中这部分声明将放在头文件.h中而构造函数及成员函数的定义则放在.cpp文件中classx{public:x(inta,intb, string c);voidprint_data();private://类数据成员的变量名最好在开头加一个字母m即memberintma;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: 2mb: 3mc: dwkw声明时提供初值如果在类的声明中就对数据成员提供初值而不在初始化列表中提供程序可以执行输出ma的值为1。1234567891011classx{public:x(inta,intb, string c);voidprint_data();private:intma 1;//声明时提供初值intmb;string mc;};//去掉初始化列表x::x(inta,intb, string c):mb(b), mc(c){}这一做法在早期版本不予支持但从c11就可以了。[2]不过这破坏了类的抽象性并不建议这样做。查看c版本的方法[3]1cout __cplusplus endl;//输出c版本在构造函数内赋初值而不用列表前面提到省略初始化列表在构造函数的函数体内对数据成员赋值是合法的。12345678910//去掉初始化列表在构造函数体内赋值//其它代码保持不变x::x(inta,intb, string c){cout 赋值前: endl;print_data();cout 赋值后: endl;ma 4;mb 5;mc ser;}输出赋值前:ma: 4199744mb: 0mc:赋值后:ma: 4mb: 5mc: ser实际上我就没写初始化列表但系统它就会在这里执行初始化。总之就会在执行构造函数体内的语句之前初始化如果它可以自动初始化即使根本没写初始化列表。→ 啧我就像在说绕口令希望你能明白我的意思但是ma和mb都是局部作用域我不确定类作用域是否是局部作用域但从输出来看ma不是0所以应该没有能够初始化的内置类型变量不进行自动初始化mc有默认构造函数自动初始化为空字符串。而后执行构造函数体内部的语句将对ma和mb进行初始化我想这里应该是初始化而不是赋值对mc赋值。