【基础知识】c++的变量初始化
转载自:https://www.cnblogs.com/caidi/p/9679673.html
参考:https://blog.csdn.net/qq_37766667/article/details/124258726
C++中变量的初始化有很多种方式,如:默认初始化,值初始化,直接初始化,拷贝初始化,列表初始化。
1、默认初始化
默认初始化是指定义变量时 没有指定初值时 进行的初始化操作。
如:int a;这些变量被定义了而没有显式的赋予初值。
特别的,采用动态分配内存的方式(即采用new关键字)创建的变量,不加括号时(如int *p=new
int;)也是默认初始化,加了括号(如int *p=new int())为值初始化。
默认初始化变量的值 与变量的类型 与变量定义的位置 有关系:
(1)对于内置类型变量(如int,double,bool等),如果定义在语句块外(即{}外),则变量被默认初始化为0;如果定义在语句块内(即{}内),变量将拥有未定义的值。
(2)对于类类型的变量(如string或其他自定义类型),不管定义于何处,都会执行默认构造函数。如果该类没有默认构造函数,则会引发错误。因此,建议为每个类都定义一个默认构造函数(=default)。
详见下面第7条具体阐述。
2、值初始化
值初始化是指使用了初始化器(即使用了圆括号或花括号)但却没有提供初始值的情况。
例如:int *p = new int(); vector<string> vec(10);
注意,若不采用动态分配内存的方式(即不采用new运算符),写成int a();是错误的值初始化方式,因为这种方式是声明了一个函数而不是进行值初始化。
如果一定要进行值初始化,必须结合拷贝初始化使用,即写成int a=int();值初始化和默认初始化一样,对于内置类型初始化为0,对于类类型则调用其默认构造函数,如果没有默认构造函数,则不能进行初始化。
3、直接初始化
直接初始化是指采用小括号的方式进行变量初始化(小括号里一定要有初始值,如果没提供初始值,那就是值初始化了!)。
例如:int a(12); vector<int> ivec(ivec2);string s("123456");等等。
直接初始化直接调用与实参匹配的构造函数。
4、拷贝初始化
拷贝初始化是指采用等号(=)进行初始化的方式,编译器把等号右侧的初始值拷贝到新创建的对象中去。
例如int a=12;string s=string("123456");等等。拷贝初始化看起来像是给变量赋值,实际上是执行了初始化操作,与先定义再赋值本质不同。
拷贝初始化首先使用指定构造函数创建一个临时对象,然后用拷贝构造函数将那个临时对象拷贝到正在创建的对象。
直接初始化与拷贝初始化区别
简而言之,拷贝初始化使用“=”符号,而直接初始化将初始化式放在圆括号中。
(1)对于内置类型变量(如int,double,bool等),直接初始化与拷贝初始化差别可以忽略不计。
(2)对于类类型的变量(如string或其他自定义类型),直接初始化调用类的构造函数(调用参数类型最佳匹配的那个),拷贝初始化调用类的拷贝构造函数。
特别的,当对类类型变量进行初始化时,如果类的构造函数采用了explicit修饰而且需要隐式类型转换时,则只能通过直接初始化而不能通过拷贝初始化进行操作。
5、列表初始化
列表初始化是C++ 11新引进的初始化方式,它采用一对花括号(即**{}**)进行初始化操作。能用直接初始化和拷贝初始化的地方都能用列表初始化,而且列表初始化能对容器进行方便的初始化,因此在新的C++标准中,推荐使用列表初始化的方式进行初始化。
列表初始化的应用场景有:int a{12};string s{"123"};vector<int> vec{1,2,3};
在某些情况下,初始化的真实含义依赖于传递初始值时用的是花括号还是圆括号。
例如,用一个整数来初始化vector时,整数的含义可能是vector对象的容量也可能是元素的值。类似的,用两个整数来初使化vector时,这两个整数可能一个是vector对象的容量,另一个是元素的初值,也可能它们是容量为2的vector对象中两个元素的初值。通过使用花括号或圆括号可以区分上述这些含义:
- vectorv1(10); //v1有10个元素,每个的值都是0
- vector v2{10}; //v2有1个元素,该元素的值时10
- vector v3(10,1); //v3有10个元素,每个的值都是1
- vector v4{10,1}; //v4有两个元素,值分别是10,1
如果用圆括号,可以说提供的值是用来构造vector对象的。例如,v1的初始值说明了vector对象的容量;v3的两个初始值则分别说明了vector对象的容量和元素的初值。
如果用的是花括号,可以表述成我们想列表初始化该vector对象。也就是说,初始化过程会尽可能地把花括号内的值当成是元素初始值的列表来处理,只有在无法执行列表初始化时才会考虑其他初始化方式。在上例中,给v2和v4提供的初始值都作为元素的值,所以它们都会执行列表初始化,vector对象v2包含一个元素而vector对象v4包含两个元素。
另一方面,如果初始化时使用了花括号的形式但是提供的值又不能用来列表初始化,就要考虑用这样的值来构造vector对象了。
例如,要想列表初始化一个含有string对象的vector对象,应该提供能赋给string对象的初值。此时不难区分到底是要列表初始化vector对象的元素还是用给定的容量值来构造vector对象:
- vector< string > v5{"hi“}; //列表初始化,v5有一个元素
- vector< string > v6(“hi”); //错误,不能使用字符串字面值构造vector对象
- vector< int > v7(10); //v7有10个默认初始化的元素,每个元素值为0
- vector< string > v8{10,“hi”}; //v8有10个值为”hi“的元素
6、使用new动态分配的默认初始化和值初始化
默认情况下,动态分配对象是默认初始化的,这意味着内置类型或组合类型的对象的值时未定义的,而类类型对象将默认构造函数进行初始化:
string *ps=new string; //初始化为空stringint *pi =new int; //pi指向一个未初始化的int
我们可以使用直接初始化方式来初始化动态分配的对象。我们可以使用传统的构造方式,在新标准下,也可以使用列表初始化(使用花括号):
int *pi=new int(1024); //pi指向的对象的值为1024string *ps=new string(10,'9'); //*派生为“9999999999”//vector有10个元素,值依次从0-9vector<int> *pv=new vector<int>{0,1,2,3,4,5,6,7,8,9};
也可以对动态分配的对象进行值初始化,只需在类型名之后跟一对空括号即可:
string *ps1=new string ;//默认初始化为空stringstring *ps=new string(); //值初始化为空stringint *pi1=new int; //默认初始化;*pi1的值未定义int *pi2=new int(); //值初始化为0;*pi2的值为0
对于定义了自己的构造函数的类类型来说,要求值初始化是没有意义的;不管采用什么方式,对象都会通过默认构造函数来初始化。但对于内置类型,两种形式的差别就大了;值初始化的内置类型对象有着良好定义的值,而默认初始化的对象的值则是未定义的。类似的,对于类中那些依赖于编译器合成的默认构造函数的内置类型成员,如果它们未在类内初始化,那么它们的值也是未定义的。
7. 默认初始值是多少?
内置类型的初始值 由 定义的位置决定
- 定义在任何函数体之外的变量被初始化为0
- 定义在函数体内部的局部变量则未定义,如果试图拷贝或者以其他形式访问该变量,则会引发错误
但是函数体内部的局部静态变量例外,如果局部静态变量没有显示的初始化,它将执行值初始化
int global_a;//值为0
short c;//值为0
int main(void)
{static int a;//值为0int b;//错误;未进行初始化
}
对于 类 类型,其默认初始值 由 类自己决定
- 如果类中的数据成员在默认构造函数中进行了赋值,则默认初始化值优先使用默认构造函数的值
- 如果在默认构造函数中没有赋值,但是该数据成员提供了类内初始值,则创建对象时,其默认初始值就是类内初始值
- 如果在默认构造函数中没有赋值且没有类内初始值,对于内置类型,则其值未定义,对于类类型,则对其进行默认初始化
class B {public:string str="123";
};
class A {public:A() {x = 1;}int x = 5;int y = 10;B b;
};
A global_a;
int main(void)
{A a;cout << global_a.x << " " << global_a.y << " " << global_a.b.str << endl;cout << a.x << " " << a.y << " " << a.b.str << endl;
}
【基础知识】c++的变量初始化相关推荐
- 《Java基础知识》Java变量的声明、初始化和作用域
<Java基础知识>Java变量的声明.初始化和作用域 一.Java变量的声明 在 Java 程序设计中,每个声明的变量都必须分配一个类型.声明一个变量时,应该先声明变量的类型,随后再声明 ...
- 《java基础知识》Java变量作用域
对于在作用域里定义的变量,作用域同时决定了它的"可见性"以及"存在时间".在JAVA里,作用域是由花括号的位置决定的.JAVA用一对大括号作为语句块的范围,称为 ...
- Java基础知识之数组的初始化和基本操作
文章目录 一.Java项目的层次 二.数组基本操作 三.初始化3类 一.Java项目的层次 (1)创建Project项目 (2)创建Module模块 (3)创建Package包 (4)创建class类 ...
- java 基础知识三 java变量
1.作用域 {} 包围起来的代码称之为代码块,在块中声明的变量只能在块中使用 2.常量 就是固定不变的量,一旦被定义,它的值就不能再被改变. 3.变量 变量必须在程序中被定义(或声明)后才能使用,而且 ...
- C++初学基础知识——注释、变量、基本数据类型
注释 作用:在代码中添加文字说明和注释,方便自己和他人更容易的阅读代码 书写格式: 1.单行注释://注释类容 *通常放在一行代码的上方或末尾,对改行代码说明 2.多行注释:/注释类容/ *通常放在代 ...
- 三个变量互换值_02-Python基础知识学习-------Python变量
1 变量 变量就是可以变化的量,程序执行的本质就是一系列状态的变化,所以我们需要有一种机制能够反映或者说是保存程序执行时状态以及状态的变化. 在学习变量之前,首先需要明确Python是 解释型的强类型 ...
- 《Python编程 从入门到实践》 一、基础知识 第二章 变量和简单的数据类型
为了所谓的效率哈(其实是因为本人比较懒,emm...),这里直接从第二章开始学习,但是考虑一些小白同学还是给大家简短介绍一下第一章. 第一章主要介绍环境的搭建和一些安装问题 1.环境的搭建可参考:Py ...
- c++入门基础知识——常量和变量
系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮 ...
- (四)JS基础知识一(深入分析变量类型和计算)【不会变量,别说你会JS】
JS基础知识一(变量类型和计算) 提问 变量类型 值类型 vs 引用类型 (堆栈模型) 值类型 引用类型 typeof 运算符 深拷贝 变量计算 字符串拼接 == if语句和逻辑运算 if语句 逻辑判 ...
- VBS学习日记(二) 基础知识
VBScript 基础知识 一.变量 1.全部单引號后面的内容都被解释为凝视.(在vbsedit中ctrl+m凝视,反凝视ctrl+shift+m) 2.在 VBScript 中,变量的命名规则遵循标 ...
最新文章
- 集美大学教务处验证码识别(一)
- [锋利JQ]-图片提示效果
- dot--向量或矩阵的点乘
- 科大星云诗社动态20210824
- 数据结构与算法 -- 时间复杂度
- hdu 3671 Boonie and Clyde
- SharePoint 2010 WSP包部署过程中究竟发生什么?
- 哪款笔记本电脑好_扫地机器人哪个牌子好?口碑最好的扫地机器人
- XML指南——XML元素
- 【OpenCV学习笔记】【函数学习】十一(读入图像﹑显示图像和保存图像)
- OnSetCursor 及改变鼠标形状
- 贝壳如何docker安装openwrt_群晖Docker安装openwrt简单图文教程(黑白群晖均适用)...
- ffmpeg 下载网上m3u8的视频文件
- 视频怎么加水印?这里有你想要的答案
- 关于英文论文写作的初步总结和资料推荐
- 西瓜书习题 - 4.决策树
- 导航定位用户向服务器发送位置请求6,跨平台的地理位置定位方法、平台及定位接入服务器...
- Mysql数据库学习笔记(2020-04-18 星期六)
- VUE 保留 四位小数
- bert模型可以做文本主题识别吗_文本匹配方法系列––BERT匹配模型