C++学习笔记总结练习:初始化的方法

本文详细介绍了C++中的五种初始化方法:默认初始化、值初始化、直接初始化、拷贝初始化和列表初始化,包括它们的语法、原理和适用场景。特别强调了类类型和aggregate类型的初始化规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

初始化方法

参考文献

1 初始化方法

C++中的初始化主要包括五种:

  • 默认初始化
  • 值初始化
  • 直接初始化
  • 拷贝初始化
  • 列表初始化
class Car{
public:
    int a=0;
    int b=1;

    Car(int aa,int bb):a(aa),b(bb){};//初始化列表,进行初始化
    Car(int aa):Car(aa,0){};//委托构造函数,使用第一个构造函数进行构造。
    Car():Car(0,0){};//默认构造函数,委托构造函数
    string m="fjeioaf";
    string *n=&m;
};

//一下是初始化方法
    Car t1(3,4);//调用构造函数
    Car t2 = Car(3,4);//调用构造函数
    // Car* t = new Car(3,4);
    Car tt{3,4};//可以调用构造函数
    vector<Car> ttt{Car(3.4),Car(5,6)};

默认初始化

默认初始化是定义对象时,没有使用初始化器,也即没有做任何初始化说明时的行为。

int i;
vector<int> v;

原理:

这些变量被定义了而不是仅仅被声明(因为没有extern关键字修饰),而且没有显式的赋予初值。特别的,如果采用动态分配内存的方式(即采用new关键字)创建的变量,不加括号时(如int *p=new int;)也是默认初始化,加了括号(如int *p=new int())为值初始化。变量的值与变量的类型与定义的位置有关系。

  1. 对于内置类型变量(如int,double,bool等),如果定义在语句块外(即{}外),则变量被默认初始化为0;如果定义在语句块内(即{}内),变量将拥有未定义的值。

  2. 对于类类型的变量(如string或其他自定义类型),不管定义于何处,都会执行默认构造函数。如果该类没有默认构造函数,则会引发错误。因此,建议为每个类都定义一个默认构造函数(=default)。

值初始化

未明确的直接初始化

  • 值初始化是值使用了初始化器(即使用了圆括号或花括号)但却没有提供初始值的情况。
int i{};
new int();
new int{}; 

原理:

  1. 当不采用动态分配内存的方式(即不采用new运算符)时,写成int a();是错误的值初始化方式,因为这种方式声明了一个函数而不是进行值初始化。
  2. 如果一定要进行值初始化,必须结合拷贝初始化使用,即写成int a=int();
  3. 值初始化和默认初始化一样,对于内置类型初始化为0,对于类类型则调用其默认构造函数,如果没有默认构造函数,则不能进行初始化。

直接初始化和拷贝初始化

从形式而言,两者相对

  • 直接初始化与拷贝初始化对应,其内部实现机理不同。
    • 直接初始化是指采用小括号的方式进行变量初始化(小括号里一定要有初始值,如果没提供初始值,那就是值初始化了!)。
    • 拷贝初始化是指采用等号(=)进行初始化的方式。拷贝初始化看起来像是给变量赋值,实际上是执行了初始化操作,与先定义再赋值本质不同。
vector<int>      v1(10);    //直接初始化,匹配某一构造函数
vector<string>   v2(10);    //直接初始化,匹配某一构造函数
vector<int>      v3=v1;     //拷贝初始化,使用=进行初始化

原理:

  1. 对于内置类型变量(如int,double,bool等),直接初始化与拷贝初始化差别可以忽略不计。

  2. 对于类类型的变量(如string或其他自定义类型),直接初始化调用类的构造函数(调用参数类型最佳匹配的那个),拷贝初始化调用类的拷贝构造函数。

列表初始化

是一个特例,跟之前的初始化方式兼容,并不独立。可以替代、结合上边的初始化方法。

列表初始化是C++ 11 新引进的初始化方式,它采用一对花括号(即{})进行初始化操作。能用直接初始化和拷贝初始化的地方都能用列表初始化,而且列表初始化能对容器进行方便的初始化,因此在新的C++标准中,推荐使用列表初始化的方式进行初始化。

[new] T [object] { arg1, arg2, ... };
  • 如果T是aggregate集合类型,list对object成员逐个初始化。
  • 如果T不是aggregate类型,编译器查找最匹配的list参数的T的构造函数。
    举例:
int a{3};//列表初始化----直接初始化
vector<int> b{3,4,5};//列表初始化----集合直接初始化
Car t{3,4};//列表初始化----直接初始化,构造函数。
vector<Car> ttt{Car(3.4),Car(5,6)};
  • 所有其他初始化形式都是list initialization的特殊表现形式或者与其相关。理解的要点在于,list中的参数要么按构造函数的参数声明顺序,要么按aggregate类型成员声明顺序,逐个赋值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

onnx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值