c++11——列表初始化
1. 使用列表初始化
在c++98/03中,对象的初始化方法有很多种,例如
int ar[3] = {1,2,3};
int arr[] = {1,2,3}; //普通数组
struct A{
int x;
struct B{
int y;
int z;
} b;
}a = {1, {3,4}}; //POD类型,可以直接使用memcpy复制的对象 int i = 0;
Foo foo = f;//拷贝初始化 int i(0);
Foo f(123); //直接初始化
在c++98/03中,普通数组合POD类型,可以通过初始化列表来进行初始化。c++11中,可以对任意类型对象使用初始化列表进行初始化。
列表初始化就是在一个变量后给出一个={},或者直接一个{},括号中含有需要的数据。
class Foo{
public:
Foo(int){};
private:
Foo(const Foo&);
};
int main(){
Foo a1(123);
Foo a2 = 123; //先隐式转换将123转化成一个Foo对象,然后调用operator=进行拷贝构造。
//错误,不能使用拷贝构造函数 Foo a3 = {123}; //列表初始化,虽然使用了=,但仍然是列表初始化,私有的拷贝构造无效
Foo a4{123}; //列表初始化
int a5 = {1};
int a6{2}; //new 操作符等可以使用圆括号进行初始化的地方,也可以使用列表初始化
int* a = new int{1, 2, 3};
double b = double{12.00};
int* arr = new int[3]{2,4,5}; //列表初始化还可以直接使用在函数的返回值上
struct Foo{
Foo(int, double){};
};
Foo func(void){
return {123, 12.00}; //返回构造的Foo对象,使用列表初始化
}
return 0;
}
2. 列表初始化的使用细节
c++11在进行列表初始化的时候,需要进行初始化的对象为聚合体。
c++聚合体
聚合类型的定义:
(1)类型是一个普通数组
(2)类型是一个类,而且:
(a)无用户自定义的构造函数
(b)无私有或保护的非静态数据成员
(c)无基类
(d)无虚函数
(e)不能有{}和=直接初始化的非静态数据成员
对于情形(e),举个例子
struct ST{
int x;
double y = 0.0;
};
ST s{1, 2.3}; //错误,不能有{}或=直接初始化的非静态数据成员
在c++98/03中,y这种非静态数据成员,本身就不能在声明时进行这种初始化工作,但是在c++11中,非静态数据成员也可以在声明的同时进行初始化工作(即使用{}或=初始化)。
struct ST{
int x;
int y;
ST(int a, int b):x(0), y(0){};
};
ST st{1, 2}; //这里进行初始时,不会进行列表初始化,而是调用的构造函数。因此,st.x = 0, st.y = 0.
聚合类型的定义并不是递归的,即当一个类的非静态成员是非聚合类型时,这个类也可能是聚合类型。
struct ST{
int x;
double y;
private:
int z;
};
ST s{1, 2.4, 1};//错误,不是聚合类型,无法使用列表初始化
struct Foo{
ST st;
int x;
double y;
};
Foo foo{{}, 1, 2.3};//虽然ST并不是一个聚合类型,但是Foo为一个聚合类型。对于非聚合类型成员st初始化时,**使用空的{},相当于调用无参构造函数**
c++11的初始化列表赋值
对于一个聚合类型,使用初始化列表相当于对其中的每个元素分别赋值;而对于非集合类型,则需要先自定义一个合适的构造函数,此时使用初始化列表将调用它对应的构造函数。
3. 初始化列表
c++11中的stl容器拥有和未显示指定长度的数组一样的初始化能力,代码如下:
int arr[]{1,2,3};
std::map<std::string,int>mm={
{"123", 1}, {"hello", 2}, {"fuck", 3}
};
std::set<int> = {1,2,3};
stl中的容器是通过使用std::initializer_list 这个轻量级的模板来实现上述功能。
std::initializer_list
(1)它是一个轻量级的容器类型,内部定义了iterator等容器必须的概念
(2)对于std::initializer_list< T>而言,它可以接受任意长度的初始化列表,但要求元素必须为类型T
(3)它有三个成员接口: size(), begin(), end()
(4)它只能被整体初始化或赋值,不能单独修改其中的某个元素(因为由上一条,知道它不提供接口)
(5)它内部存放的是元素的引用,因此不会进行拷贝操作,所以需要注意在使用的时候保证内部存放的元素有效期
std::initializer_list<int> list = {1,2,3,4};
size_t n = list.size(); // 4
list = {4, 5, 6}; //整体赋值
4. 防止类型收窄
类型收窄指的是导致数据内容发生变化或者精度丢失的隐式类型转换。类型收窄包含如下几种情况:
(1)从一个浮点数隐式转换到一个整型数
(2)从高精度浮点数转换为低精度浮点数
(3)从一个整型数隐式转换为一个浮点数,并且超出了浮点数的表示范围,如 float x= (unsigned long long )-1;
(4)从一个整型数转换为一个长度较短的整型数,并且超出了长度较短的整型数的表示范围。如char x = 3333;
在c++98/03中,出现上面的类型收窄的情况,编译器不会报错。在c++11中,可以通过列表初始化来检查以及防止类型收窄。
int a = 1.1; //可以
int a = {1.1}; //出错
c++11——列表初始化的更多相关文章
- C++11 列表初始化
在我们实际编程中,我们经常会碰到变量初始化的问题,对于不同的变量初始化的手段多种多样,比如说对于一个数组我们可以使用 int arr[] = {1,2,3}的方式初始化,又比如对于一个简单的结构体: ...
- C++11的初始化列表
初始化是一个非常重要的语言特性,最常见的就是对对象进行初始化.在传统 C++ 中,不同的对象有着不同的初始化方法,例如普通数组.POD (plain old data,没有构造.析构和虚函数的类或 ...
- c++11之初始化列表
一.前言 C++的学习中.我想每一个人都被变量定义和申明折磨过,比方我在大学笔试过的几家公司.都考察了const和变量,类型的不同排列组合,让你差别有啥不同.反正在学习C++过程中已经被折磨惯 ...
- C++11之列表初始化
1. 在C++98中,标准允许使用花括号{}来对数组元素进行统一的集合(列表)初始化操作,如:int buf[] = {0};int arr[] = {1,2,3,4,5,6,7,8}; 可是对于自定 ...
- C++11常用特性介绍——列表初始化
一.列表初始化 1)C++11以前,定义初始化的几种不同形式,如下: int data = 0; //赋值初始化 int data = {0}; //花括号初始化 int data(0); / ...
- 第8课 列表初始化(3)_防止类型收窄、explicit关键字
1. 防止类型收窄 (1)类型收窄:指的是导致数据内容发生变化或者精度丢失的隐式类型转换. (2)类型收窄的几种情况: ①从浮点数隐式转换为整型数,如int i=2.2; ②从高精度浮点数隐式转换为低 ...
- initializer_list、初始化列表、列表初始化
什么是列表初始化 使用一个花括号来初始化变量,表现形式如下: std::vector<int>a{1,2,3,4,5}; 或者 std::vector<int>a = {1,2 ...
- 列表初始化 分析initializer_list<T>的实现
列表初始化(1)_统一初始化 1. 统一初始化(Uniform Initialization) (1)在C++11之前,很多程序员特别是初学者对如何初始化一个变量或对象的问题很容易出现困惑.因为可以用 ...
- C++统一初始化语法(列表初始化)
引言 要是世上不曾存在C++14和C++17该有多好!constexpr是好东西,但是让编译器开发者痛不欲生:新标准库的确好用,但改语法细节未必是明智之举,尤其是3年一次的频繁改动.C++带了太多历史 ...
随机推荐
- JS地毯式学习一
1.<noscript> 现代浏览器都对JavaScript进行了支持,一般是在用户的浏览器禁用了脚本的情况下才会显示<noscript>的内容. 包含在<noscrip ...
- 应用层timer_如何序列化timer
应用层使用timer可以启动多个timer(每个timer管理一个目标时间),也可启用一个timer来管理多个目标时间. 多个timer时每个timer占用一部分空间,且存在多个timer同时到期的先 ...
- Jenkins+ Xcode+ 蒲公英 实现IOS自动化打包和分发
Jenkins+ Xcode+ 蒲公英 实现IOS自动化打包和分发 直接入正题: Screen Shot 2015-09-18 at 16.56.20.png Mac上安装Jekins jekins下 ...
- Entity Framework管理实体关系(一):管理一对一关系
我们现在已经知道如何使用Code First来定义简单的领域类,并且如何使用DbContext类来执行数据库操作.现在我们来看下数据库理论中的多样性关系,我们会使用Code First来实现下面的几种 ...
- .net垃圾回收
垃圾回收器(gc)用来在.NET中进行内存管理,特别是它可以恢复正在运行的应用程序需要的内存. .NET运行库采用的方法是垃圾回收器,这是一个程序,其目的是清理内存.方法是所有动态请求的内存都分配到堆 ...
- 上手并过渡到PHP7(5)——轻量级“集合”迭代器-Generator
轻量级“集合”迭代器-Generator泊学视频链接泊阅文档链接Generator是PHP 5.5加入的新语言特性.但是,它似乎并没有被很多PHP开发者广泛采用.因此,在我们了解PHP 7对Gener ...
- 让PHP7达到最高性能的几个Tips
PHP7 已经发布了,作为PHP十年来最大的版本升级,最大的性能升级,PHP7在多放的测试中都表现出很明显的性能提升,然而,为了让它能发挥出最大的性能,我还是有几件事想提醒下. PHP7 VS PHP ...
- 判断一个string是否以数字开头
public static void main(String[] args) { Pattern pattern =null; String content = "30. ...
- spring 优点
spring 的优点?1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦 2.可以使用容易提供的众多服务,如事务管理,消息服务等 3.容器提供单例模式支持 4.容器提供了AOP技术,利用它很容易实 ...
- HEVC/H.265 的未来必须是使用并行处理(OpenCL?) OpenCV和OpenCL区别
1 扩展库简介 OpenCV(Open Source Computer Vision Library)是一个致力于实时处理计算机视觉问题的开源库.它最初由Intel公司开发,以GPL许可协议发布,后来 ...