类与对象(三)--构造函数体中的赋值和初始化列表的区别

简介: 类与对象(三)--构造函数体中的赋值和初始化列表的区别

🎧1构造函数体赋值

🔎在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。

⭐️就像上述代码中的构造函数,其函数体的语句只能被称为赋予初值而不能称为初始化。因为初始化是在定义的同时赋值且只赋值一次,而构造函数体内是先定义后赋值。

🎧2初始化列表

2.1什么叫初始化列表?

🔎在C++中,构造函数的初始化列表是一种用于在创建对象时对成员变量进行初始化的特殊语法。它出现在构造函数的函数体之前使用冒号 : 分隔构造函数的参数列表和初始化列表,初始话列表中的语句用逗号“,”隔开

2.2初始化列表的作用?

🔎可以在对象创建时直接对成员变量进行初始化,而不需要在构造函数的函数体中再次进行赋值操作。这可以提高代码效率,并且在一些情况下是必要的,例如对于常量成员变量或引用成员变量。

2.3使用举例

🔎 以上代码乍一看这初始化列表和函数体赋值好像就是使用方式不一样。实则不然。就从功能角度来说,初始化列表只能用于初始化。而构造函数体中,可以实现其它的操作,比如打印。

2.4初始化列表的具体使用细则

1.每个成员在初始化列表中只能出现一次(初始化只能初始一次)

2.类中包含以下成员,必须放在初始化列表位置进行初始化

🔥引用成员变量

🔥const成员变量

🔥自定义类型成员变量(且该类没有默认构造函数)

💬引用成员变量比较好理解,因为之前我们已经讲过引用类型的变量必须初始化且不能被再次赋值。const成员变量无法被赋值,只能放在初始化列表进行初始化,而自定义类型如果没有默认的构造函数的话(编译器生成的无参的),也就不能先定义后再赋值,且该类里面也可能又引用或者const成员变量,所以必须再定义的同时初始化。

3. 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,
一定会先使用初始化列表初始化。

4.成员变量在类中声明次序就是其在初始化列表中的初始化顺序与其在初始化列表中的先后
次序无关。

举例:

观察以下代码

class A
{
public:
  A(int a)
    :_a1(a)
    , _a2(_a1)
  {}
  void Print() {
    cout <<"a1=" << _a1 << " " <<"a2=" << _a2 << endl;
  }
private:
  int _a2;
  int _a1;
};
void test1() {
    A aa(1);
  aa.Print();
}

如果调用函数test1()会输出什么呢?

💬我们可以看到,虽然再初始化列表中_a1的顺序在_a2前面,但是由于声明顺序是_a2先声明,所以先初始化_a2.也就是先将_a1的值赋给_a2,但是由于此时的_a1并没有初值是一个随机值,所以会得到这样的结果。

🎧3两者的区别🚦

  1. 执行时机:
  • 初始化列表: 初始化列表会在进入构造函数的函数体之前执行,即在构造函数开始执行之前。这确保了在进入函数体之前,所有的成员变量都已经得到了适当的初始化。
  • 构造函数体内的赋值: 构造函数体内的赋值则是在进入构造函数的函数体后执行的操作。

语法形式:

  • 初始化列表: 使用冒号 : 后面跟着成员变量的初始化语句。
  • 构造函数体内的赋值: 在构造函数的函数体内,通过赋值语句对成员变量进行初始化。

🎧4总结🚦

在实践中,推荐使用初始化列表,特别是对于非静态常量成员、引用成员或具有自定义构造函数的成员。这样可以确保在进入构造函数体之前,所有成员都得到了正确的初始化。

相关文章
|
3月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
156 5
|
3月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
170 4
|
8月前
|
编译器 C++
【C++】类和对象③(类的默认成员函数:赋值运算符重载)
在C++中,运算符重载允许为用户定义的类型扩展运算符功能,但不能创建新运算符如`operator@`。重载的运算符必须至少有一个类类型参数,且不能改变内置类型运算符的含义。`.*::sizeof?`不可重载。赋值运算符`=`通常作为成员函数重载,确保封装性,如`Date`类的`operator==`。赋值运算符应返回引用并检查自我赋值。当未显式重载时,编译器提供默认实现,但这可能不足以处理资源管理。拷贝构造和赋值运算符在对象复制中有不同用途,需根据类需求定制实现。正确实现它们对避免数据错误和内存问题至关重要。接下来将探讨更多操作符重载和默认成员函数。
|
8月前
|
存储 编译器 C++
【C++】类和对象③(类的默认成员函数:拷贝构造函数)
本文探讨了C++中拷贝构造函数和赋值运算符重载的重要性。拷贝构造函数用于创建与已有对象相同的新对象,尤其在类涉及资源管理时需谨慎处理,以防止浅拷贝导致的问题。默认拷贝构造函数进行字节级复制,可能导致资源重复释放。例子展示了未正确实现拷贝构造函数时可能导致的无限递归。此外,文章提到了拷贝构造函数的常见应用场景,如函数参数、返回值和对象初始化,并指出类对象在赋值或作为函数参数时会隐式调用拷贝构造。
|
8月前
|
存储 编译器 C语言
【C++】类和对象②(类的默认成员函数:构造函数 | 析构函数)
C++类的六大默认成员函数包括构造函数、析构函数、拷贝构造、赋值运算符、取地址重载及const取址。构造函数用于对象初始化,无返回值,名称与类名相同,可重载。若未定义,编译器提供默认无参构造。析构函数负责对象销毁,名字前加`~`,无参数无返回,自动调用以释放资源。一个类只有一个析构函数。两者确保对象生命周期中正确初始化和清理。
|
9月前
|
Java C++
类与对象(三)--内部类、匿名对象
类与对象(三)--内部类、匿名对象
类与对象(三)--内部类、匿名对象
|
存储 编译器 C语言
【C++基础】类与对象(中):默认成员函数、构造函数、析构函数、拷贝构造、赋值重载函数……
【C++基础】类与对象(中):默认成员函数、构造函数、析构函数、拷贝构造、赋值重载函数……
98 0
|
安全 编译器 C++
[C++] 类与对象(中)类中六个默认成员函数(1)上
[C++] 类与对象(中)类中六个默认成员函数(1)上
|
9月前
|
编译器 C++
【c++】构造函数赋值方式(初始化列表)
【c++】构造函数赋值方式(初始化列表)
|
存储 编译器 C++
[C++] 类与对象(中)类中六个默认成员函数(1)下
[C++] 类与对象(中)类中六个默认成员函数(1)下