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}; //出错
时间: 2024-11-08 02:51:23

c++11——列表初始化的相关文章

C++11列表初始化

列表初始化:1.旧语法中定义了初始化的几种不同形式,如下: int data = 0; //赋值初始化 int data = {0}; //花括号初始化 int data(0); //构造初始化 int data{0}; //花括号初始化 2.C++11以旧语法中花括号初始化形式为基础,设计了列表初始化语法,统一了不同的初始化形式. 数据类型 变量{初始化列表} 1 #include <iostream> 2 #include <iterator> 3 using namespac

c++11之初始化列表

一.前言 C++的学习中,我想每个人都被变量定义和申明折磨过,比如我在大学笔试过的几家公司,都考察了const和变量,类型的不同排列组合,让你区别有啥不同.反正在学习C++过程中已经被折磨惯了,今天再来看看重温下那段"辉煌的历史".先来看一段代码: Player pa; // (a) Player pb(); // (b) Player pc = Player(); // (c) Player pd(Player()); // (d) pd = Player() // (e) a,b,

[C++11笔记001]修改通用库中的XDynamicArray,使它可以支持C++11的初始化列表和for循环

今天,有空翻了一下<C++Primer plus(第六版)>,看到里面有介绍新的for循环和初始化列表,但是我实现的动态数组XDynamicArray不支持这些新特性,没办法,只好进行改造了. 首先是for循环,如下面的样式 for(auto e:stList) { cout<<e<<endl; } 是于就各种google,和查找C++11的array的源代码,总结:就是提供一个标准的iterator和begin,end这两个方法,就可以了. 是于定义了一个iterat

C++11之列表初始化

1. 在C++98中,标准允许使用花括号{}来对数组元素进行统一的集合(列表)初始化操作,如:int buf[] = {0};int arr[] = {1,2,3,4,5,6,7,8}; 可是对于自定义的类型,却是无法这样去初始化的,比如STL标准模板库中容器,使用的频率非常之高,如vector,若要初始化其内容,则需要每次进行push_back 或使用迭代器去初始化,这是极其不便的.C++11 中,可以”列表初始化“方式来快速的初始化内置类型或STL中容器. 2.集合(列表)的初始化方式已经成

C++列表初始化

在C++11中,使用花括号来初始化变量得到全面的应用,也可以用花括号来对变量赋值.当用于内置类型变量时,这种初始化的一个重要特点是如果使用列表初始化且初始值存在丢失信息的风险,编译器将报错. int _tmain(int argc, _TCHAR* argv[]) { long double ld = 3.1415926536; int a{ ld }; int b = { ld }; int c(ld); int d = ld; return 0; } 编译将得到以下错误: (11): err

【共读Primer】51.[6.3]返回类型和return语句--列表初始化返回值 Page203

列表初始化返回值 C++11规定可以以列表初始化的方式来进行返回值的表达. vector<string> process() { if(expected.empty()) return {}; else if(expected == actual) return {"funcationX", "okay"}; else return {"funcationX", expected, actual}; } 主函数main的返回值 非vo

列表初始化 分析initializer_list&lt;T&gt;的实现

列表初始化(1)_统一初始化 1. 统一初始化(Uniform Initialization) (1)在C++11之前,很多程序员特别是初学者对如何初始化一个变量或对象的问题很容易出现困惑.因为可以用小括号.大括号或赋值操作符等多种方式进行初始化. (2)基于这个原因,C++11引入了“统一初始化”的概念.这意味着我们可以使用{}这种通用的语法在任何需要初始化的地方. [实例分析]初始化列表 #include <iostream> #include <vector> #includ

列表初始化

1 int var = 0; 2 int var = {0}; 3 int var {0}; 4 int var(0); 无论是初始化对象还是某些时候为对象赋新值,都可以用这样一组右花括号括起来的初始值. 当用于内置类型的变量时,这种初始化形式有一个重要特点:如果我们使用列表初始化且初始值存在丢失信息的风险,则编译器将报错,也就是说安全性比那些作转换的更高: 1 long double ld = 3.14 2 int a{ld},b={ld};// 错误:没发生转换,因为存在丢失信息的风险 3

Loadrunner 11.00 初始化失败; 通信错误。 Error (-81024): LR_VUG: The &#39;WS_SOAP&#39; type is not supported on &#39;WIN32&#39; platforms .

搜索LR安装目录bin文件夹下有个"wlrun.exe"的文件,邮件点击"属性"->"兼容性"->兼容模式中选择"windows 7",确认后重新打开即可,win10下是这个选项,其他操作系统挨个试一下,总有一个可以的! Loadrunner 11.00 初始化失败; 通信错误. Error (-81024): LR_VUG: The 'WS_SOAP' type is not supported on 'WIN3