精华内容
下载资源
问答
  • c++类中初始化
    千次阅读
    2021-06-29 10:00:14
    摘要:在C++11之后,声明时初始化->初始化列表->构造函数初始化。

    本文分享自华为云社区《如何编写高效、优雅、可信代码系列(3)——类成员初始化的三种方式》,原文作者:我是一颗大西瓜。

    首先,先得了解一下C++支持哪几种类成员初始化的方式,你常用的又是哪一种。

    • 初始化方式一:初始化列表
    class A
    {
    public:
        int a; // 初始化列表
        A(int a_):a(a_){}
    };
    • 初始化方式二:构造函数初始化
    class A
    {
    public:
        int a; // 初始化列表
        A(int a_, bool b) { a = a_; }
    };
    • 初始化方式三:声明时初始化(也称就地初始化,c++11后支持)
    class A
    {
    public:
        int a = 1; // 声明时初始化
        A() {}
    };

    在C++98中,支持了在类声明中使用等号“=”加初始值的方式,来初始化类中静态成员常量。这种声明方式我们也称之为“就地”声明。就地声明在代码编写时非常便利,不过C++98对类中就地声明的要求却非常高。如果静态成员不满足常量性,则不可以就地声明,而且即使常量的静态成员也只能是整型或者枚举型才能就地初始化。而非静态成员变量的初始化则必须在构造函数中进行。比如,如下代码在c++98中编译

    class Init
    {
    public:
        Init(): a(0) []
        Init(int d): a(d) {}
    private:
        int a;
        const static int b = 0;
    
        int c = 1;           // member, cannot pass build
        static int d = 0;    // member, cannot pass build
    
        static const double e = 1.3;      // not int or enum type, cannot pass build
        stati const char* const f = "e";  // not int or enum type, cannot pass build
    }

    这非常不方便,所以在C++11中,标准允许非静态成员变量的初始化有多种形式。具体而言,除了初始化列表外,在C++11中,标准还允许使用等号= 或者 花括号{} 进行就地的非静态成员变量初始化。

    struct init {
        int a = 1;
        double b {1.2};
    };

    大家知道,有几种情况下推荐优先使用列表初始化

    • const成员变量只能用成员初始化列表来完成初始化,而不能在构造函数内赋值
    • 初始化的数据成员是对象
    • 需要初始化引用成员数据

    具体的原因这里不细述,大家可以去看一下《C++ Primer》。

    构造函数初始化的本质是赋值操作("="),这个方法存在两个问题,一个是比起初始化列表和就地初始化,此方式的效率偏低;第二个是可能存在错误隐患。

    先说第一个,赋值过程中会产生临时对象,临时对象的构造析构会造成效率损耗,初始化列表的方式就避免了产生临时对象缩带来的问题。

    第二个是,如果你没有重写或者禁止赋值构造函数,c++会悄悄的加上默认的赋值构造函数,这个时候也有可能带来问题。

    从C++11之后,这三种初始化的方法都可以使用,并不会存在冲突,但是,他们之间是有优先级顺序的,这个优先级来源于他们在初始化的时间顺序,后面初始化的会把前面的覆盖掉,成员变量的初始化顺序是

    声明时初始化->初始化列表->构造函数初始化

    因此假如三种初始化方式同时存在的话,那么最后保留的成员变量值肯定是构造函数中初始化的值。

    #include <iostream>
    using namespace std;
    class A 
    {
    public:
        int a = 1;
        A(int a_) :a(2) { a = 3; }
    };
    
    int main()
    {
        A a;
        cout << "a.a=" << a.a << endl;
        return 0;
    }
    
    // a.a=3

    既然初始化方式这么多,那么什么时候适用哪种呢?

    1. 声明时初始化的使用场景

    • 一个优点是直观,你在声明的时候顺便给一个初始值,bravo,别人在看你代码的时候,点一下调到声明也能看到你赋予的初始值,不用再去看构造函数那里给的什么值
    • 第二个优点更有用了,比如你要定义多个构造函数,每个构造函数都用列表初始化的方法初始化,多麻烦呀,请看下面的例子,妈妈看了再也不用担心我想用其他初始化方法了
    class Group {
    public:
        Group() {}
        Group(int a): data(a) {}
        Group(Mem m): mem(m) {}
        Group(int a, Mem m, string n): data(a), mem(m), name(n) {}
    private:
        int data = 1;
        Mem mem{0};
        string name{"Group"};
    };

    2. 列表初始化的使用场景

    前面说过了三个场景,这里赘述一下

    • const成员变量只能用成员初始化列表来完成初始化,而不能在构造函数内赋值
    • 初始化的数据成员是对象
    • 需要初始化引用成员数据

    但是,需要注意列表初始化的顺序,不过IDE会提示你的

    3. 构造函数初始化的使用场景

    • 第一个就是拷贝和赋值构造函数里(不然怎么叫赋值构造函数呢)
    • 第二个就是比较无聊的情况了,比如你想把几个成员函数都初始化成一个值,请看下面例子
    class Group {
    public:
        Group() {data1 = data2 = data3 = 0;}
    private:
        int data1;
        int data2;
        int data3;
    };

    一言以蔽之,优先就地初始化和列表初始化。

    点击关注,第一时间了解华为云新鲜技术~

    更多相关内容
  • c++中初始化列表

    千次阅读 2022-04-13 21:52:28
    4. 成员变量在类中声明次序就是其在初始化列表初始化顺序,与其在初始化列表的先后次序无关 初始化列表的概念和使用 初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面...

    目录

    初始化列表的概念和使用

    初始化列表的注意事项

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

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

    3.最好使用初始化列表进行初始化,因为对于自定义类型,我们还是需要使用初始化列表进行初始化的

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


    初始化列表的概念和使用

    初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式

    Data(int year = 0, int month = 0, int day = 0) : _year(year), _month(month), _day(day)	
    //以构造函数声明后的:(冒号)开始,每个成员变量用,(逗号)隔开,()括号中放的是初始化的值
    	{}

    初始化列表的注意事项

    一个对象的当个成员变量在初始化列表是定义阶段(构造函数),而在构造函数里面就是赋值了,假如我们没写成员变量的初始化列表也会初始化,只不过初始化为随机值

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


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

    1、引用成员变量

    class Data
    {
    public:
    	Data(int year = 0, int month = 0, int day = 0):_a(year)	//使用初始化列表初始化
    	{
    		_year = year;
    		_month = month;
    		_day = day;
    	}
    
    private:
    	int _year;
    	int _month;
    	int _day;
    	int& _a;	//定义一个引用成员变量
    };

    引用在类中只是被声明,没有被定义,所以可以先不初始化,当我们实例化一个对象之后,必须进行初始化,所以引用要在初始化列表初始化
     

    2、const成员变量

    class Data
    {
    public:
    	Data(int year = 0, int month = 0, int day = 0):_a(0)	//使用初始化列表初始化
    	{
    		_year = year;
    		_month = month;
    		_day = day;
    	}
    
    private:
    	int _year;
    	int _month;
    	int _day;
    	const int _a;	//定义一个const修饰的成员变量
    };

    const修饰的成员变量不能够被修改,所以需要在定义时候进行初始化
     

    3、自定义类型成员(该类没有默认构造函数)

    class A
    {
    public:
    	A(int x)	//因为我们写了构造函数,所以这个类没有默认构造函数了
    	{
    		_a = x;
    	}
    public:
    	int _a;
    };
    
    class Data
    {
    public:
    	Data(int year = 0, int month = 0, int day = 0) :a(0)	//使用初始化列表初始化
    	{
    		_year = year;
    		_month = month;
    		_day = day;
    	}
    
    private:
    	int _year;
    	int _month;
    	int _day;
    	A a;	//创建一个类的对象
    };

    因为类没有默认构造函数,所以类里面的成员变量不会自动赋值,我们必须对它进行初始化,这个初始化就在初始化列表

    3.最好使用初始化列表进行初始化,因为对于自定义类型,我们还是需要使用初始化列表进行初始化的

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

    #include<iostream>
    using namespace std;
    
    class A
    {
    public:
    	A(int a)
    		:_a1(a)
    		, _a2(_a1)    //使用初始化列表初始化
    	{}
    	void Print() {
    		cout << _a1 << " " << _a2 << endl;
    	}
    private:
    	int _a2;
    	int _a1;
    };
    
    int main() {
    	A aa(1);
    	aa.Print();
    }

    结果为因为初始化列表进行初始化的时候是按照成员变量声明的顺序来的,所以_a2先被初始化为随机值,_a1再被初始化为a

     

    展开全文
  • C++类初始化列表

    千次阅读 2022-06-06 16:14:32
    初始化列表是类中构造函数的一部分,用于实例化类中变量时 赋初值。

    意义

    初始化列表是类中构造函数的一部分,用于实例化类中变量时 赋初值。

    需要先了解  构造函数的基本知识。CSDN-构造函数https://blog.csdn.net/weixin_44212838/article/details/124901019?spm=1001.2014.3001.5501

    用法

    在函数头与函数体之间,用一个‘ ’列出变量,变量后用‘()’ 给出实例化该变量时要赋予的初值

    用例:

    class Date {
    public:
    
        Date(int year, int month, int day)
            :_year(year), _month(month),_day(day)//初始化列表
        {
            ;
        }
    private:
        int _year;
        int _month;
        int _day;
    };

    与在函数体内初始化的区别

    初始化列表 实在实例化,也就是为变量开辟空间后,立刻赋予初始值。

    类似于 

    int a=10;//实例化时赋予初始值

    而在构造函数体内初始化 ,则是先为变量开辟空间,后赋予值。

    类似于

    int a;//先为变量开辟空间
    a=10;//后赋予值

    常见的使用场景

    1.调用类中 自定义类型成员的构造函数

    #include<iostream>
    class a {
    public:
        a(int val,int date) {
            _val = val;
        }
    private:
        int _val;
        int _date;
    };
    class  A {
    public:
        A(int val = 1) 
            :ma(5,4)
        {
            _val = val;
        }
        int _val;
        a ma;
    };

    因为 class a没有默认构造函数,需要主动传参,而构造函数只能在实例化对象的时候调用,并且要先实例化成员变量才会进入class A的构造函数体内,所以,只能使用class A的初始化列表来调用class a的构造函数 初始化A的 成员变量ma。 

    2.类中 const修饰的成员变量

    #include<iostream>
    class A {
    public:
    	A(int val):_val(val){}
    	const int _val;
    };
    int main() {
    	A a (2);
    	std::cout << a._val;
    	return 0;
    }

    具有常属性的变量需要在实例化时赋初值

    3.类中 引用类型的成员变量

    #include<iostream>
    class A {
    public:
    	A(int val):_val(val),mval(_val){}
    	const int _val;
    	const int& mval;
    };
    int main() {
    	A a (2);
    	std::cout << a.mval;
    	return 0;
    }

    以上这就是初始化列表非常典型的使用场景。

    展开全文
  • C++类内初始值的初始化形式

    千次阅读 2022-01-21 12:18:17
    C++类内初始值的初始化形式一.不能用圆括号给内初始值的原因二.=和花括号{}初始化的区别1.内置类型和类型2.模板先看初始化列表{}:再看=的初始化过程:==总结:==三.内初始值的初始化列表{}方式 C++11规定,...

    C++11规定,可以为数据成员提供一个类内初始值。创建对象时,类内初始值用于初始化数据成员。像下面这样,cursor和height的类内初始值均为0。

    class Screen
    {
    private:
    	int cursor = 0;
    	int height = 0;
    };
    

    一.不能用圆括号给类内初始值的原因

    C++ primer(第5版)中写道:类内初始值的提供必需以=或者花括号{}的形式不能用园括号()

    关于这一点,可以参考网上的一个说法,如下:
    由于无法避免下面的这种情况,这相当于对于int z(int);函数的声明,所以C++把用圆括号进行类内初始值定义为非法。

    class Widget 
    {
    private: 
      typedef int x;  
      int z(x);
    };
    

    二.=和花括号{}初始化的区别

    1.内置类型和类类型

    对于这两者而言,=和{}初始化的区别不大,测试如下。

    #include <iostream>     // std::cout
    #include <string>
    #include <vector>
    
    using namespace std;
    
    int main() 
    {
    	std::cout << "*****内置类型*****" << std::endl;
    
    	int ival = 1;
    
    	int ival2{ 1 };
    	int ival3 = { 1 };//实际上同ival2{ 1 }一样
    
    	std::cout <<"ival = " <<ival << std::endl;
    	std::cout <<"ival2 = " <<ival2 << std::endl;
    	std::cout <<"ival3 = " << ival3 << std::endl;
    
    	std::cout << "*****类*****" << std::endl;
    
    	string str = "aa";
    
    	string str2{ "aa" };
    	string str3 = { "aa" };//实际上同str2{ "aa" }一样
    
    	std::cout << "str = " << str << std::endl;
    	std::cout << "str2 = " << str2 << std::endl;
    	std::cout << "str3 = " << str3 << std::endl;
    
    	system("pause");
    	return 0;
    }
    

    在这里插入图片描述

    2.类模板

    对于类模板而言,我们可以看看实际上初始化列表{}和=初始化的过程:

    先看初始化列表{}:

    std::vector<std::string> vs{ "ssss" ,"dddd"};
    

    可以看到,上面的初始化的最后一步是在vector中插入初始化列表中元素

    再看=的初始化过程:

    因为它实际上是一个拷贝构造的过程,所以=的右边必须是一个同类型的值,如下所示。vs3可以看成是一个’std::vector’类型的变量,那么只能用’std::vector’类型的变量来初始化它,比如下面的vs_tmp。

    	std::vector<string> vs_tmp;
    	std::vector<string> vs3 = vs_tmp;
    

    注意,千万不能这样:std::vector<string> vs2 = "eee";
    上述初始化最后调用的是vector的拷贝构造函数,如下:
    在这里插入图片描述

    总结:

    • 初始化列表,列表中的元素就是模板的元素,如vector<string> tmp_vec= {"ddd","www"}
    • =初始化,只能用同类型,如只能用vector类型初始化vector类型

    三.类内初始值的初始化列表{}方式

    我在实际上调试时发现如下这样的一个问题:类内初始值的初始化列表{}方式编译器会报错。定义的类如下。
    这让我很迷惑,因为在上面的测试中是可以的?后来才发现,因为我用的是VS2013,而它并不是完全支持C++11标准,所以对类内初始值用初始化列表的形式可能还不支持,换一个编译器后,不再报错。

    class Wind_mgr
    {
    public:
    	void putsData()
    	{
    		str.push_back("aaa");
    	}
    private:
    	std::vector<std::string> str{"bbb"};//Error,无法从“const char [4]”转换为“const std::allocator<_Ty>”
    };
    

    最后附上vector的几种初始化形式:

    初始化格式说明
    vector v1生成一个空vector
    vector v2(V1)v2包含v1的所有元素副本
    vector v2 = v1等价于V2(V1)
    vector v3(n,val)v3被初始化为n个val值,即v3有n个重复的元素
    vector v4(n)v4是一个有n个元素的vector,只是n个元素均为值初始化值
    vector v5{a,b,c…}v5的大小就是初始化列表的大小,每个元素的值是初始化列表的值
    vector v5 = {a,b,c…}等价于V5{a,b,c…}
    vector v6 (first, last)将迭代器[first,last)区间的元素拷贝到v6
    展开全文
  • C++ 类中const数组如何初始化

    千次阅读 2021-01-20 23:24:11
    C++ 类中const数组如何初始化 (1)构造函数的初始化列表 const初始化的地方,不可以在构造函数体内赋值 (2)初始化列表初始化的写法跟普通数组一样,注意写法 # include <iostream> using namespace ...
  • c++类成员变量初始化详解

    千次阅读 2022-04-15 10:08:24
    1.类初始化顺序 当类初始化的时候,会调用其构造函数并进行初始化。当对象结束其生命周期,会调用析构函数进行资源回收。 注意在调用资深构造函数之前,首先会调用其成员变量构造函数并进行初始化,再进入自身构造...
  • C++中类初始化

    千次阅读 2019-05-05 18:08:39
    这是《C++primer》的笔记和总结,在C++类中,用来初始化类中的成员的方式多种多样,常常是依据这些变量的特性来决定的,比如const、static以及引用等类型。这里说的是最普通的初始化方式,估计用的也最少,是继承...
  • C++如何正确地在类中初始化vector成员变量

    万次阅读 多人点赞 2019-04-09 10:39:37
    错误的方法 class Foo(){ private: vector<string> name(5); //error in these 2 lines vector<...C++11以后: class Foo(){ private: vector<string> name = vector<strin...
  • C++学习——初始化

    千次阅读 2021-06-17 15:39:03
    通过构造函数进行数据成员初始化2.成员初始化方式?3.什么情况下必须使用列表初始化?4.为什么用列表初始化成员变量会快一些?5.派生构造函数的执行顺序 1.通过构造函数进行数据成员初始化 一般来说,类中的...
  • C++中类初始值列表与类内初始化

    千次阅读 2020-09-22 12:18:56
    的构造函数的作用是对其成员进行初始化。而在构造函数可以使用初始值列表为新创建的对象的成员进行赋值。 1 初始值列表 在的构造函数名之后紧跟着冒号,冒号后面是要初始化的成员名,之后是圆括号或者花括号...
  • c++类初始化原理

    千次阅读 2018-08-17 23:11:54
    一、初始化时带括号和不带括号的区别 class Test4 { public: Test3 t3; Test4(){ t3 = Test3(); cout &lt;&lt; "Test4" &lt;&lt; endl; } }; int main() { Test3 t3; cout &...
  • C++ queue初始化的坑

    千次阅读 2021-06-20 18:59:12
    C++ queue的初始化方式里没有列表初始化!就是用花括号那个。定义这种初始化的构造函数一定会有一个参数是std::initializer_list<T> init,但是queue没有! queue所有的初始化方式参见该网页。
  • C++类指针初始化

    千次阅读 2017-12-29 14:22:17
    初始化为NULL的指针可以安全的调用不涉及成员变量的成员函数而不出错,但是如果成员函数调用了成员变量则会出错,既然赋值为NULL的情况都可以使用,那么自然不初始化指针同样满足这情况。...
  • vector不是模板,list不是模板等问题。 解决方法: 1.在开头加上 #include<vector> #include<list> 2.vector和list在命名空间std里,还需要添加声明 using namespace std; 引用:......
  • 一开始,我其实不打算把初始化列表单独拿出来写一篇文章的,我打算在创建一个的那一篇文章里一起写掉,但是写着写着就发现事情没有我想的那么简单,这里面的内容还是比较多地。 二、初始化列表格式: 在构造函数...
  • c++类成员初始化方式

    万次阅读 多人点赞 2019-07-11 18:59:33
    转载自: ...常用的初始化可能如下: 1)赋值初始化 class Student { public: Student(string in_name, int in_age) { name = in_name; age = in_age; } private : string...
  • C++构造函数初始化列表与赋值

    千次阅读 2022-03-09 17:19:07
    C++类中成员变量的初始化有两种方式: 构造函数初始化列表和构造函数体内赋值。 初始化列表对成员变量做的事情叫做初始化,而构造函数体内对成员变量做的事情就叫做赋值了。 整个构造函数的执行过程包括(初始化...
  • C++ 对象的初始化

    千次阅读 2021-04-13 20:50:08
    与c语言不同,在面向对象的编程,使用构造函数对数据成员进行初始化,有多种方式。 录: 一、无参数的构造函数 二、带参数的构造函数 三、使用构造函数的参数初始化表 四、带默认参数的构造函数 对各种方式的描述...
  • C++ 成员变量初始化顺序

    千次阅读 2020-01-16 23:02:50
    首先,看一段程序: #include using namespace std;...下面是C++类成员变量初始化顺序: 1) 基类的静态变量或全局变量 2) 派生的静态变量或全局变量 3) 基类的成员变量 4) 派生的成员变量
  • C++中初始化

    千次阅读 2019-11-24 22:00:01
    初始化的概念 初始化(initialized):当对象在创建时获得了一个特定的值,称为对这个对象的初始化。 注:定义在函数体内部的内置类型的变量不被初始化(uninitialized),此类变量的值是未定义的。static的除外,...
  • c++】对象初始化

    千次阅读 2022-04-16 22:11:22
    1. 默认初始化 2.零初始化 3.值初始化 4.直接初始化 5.复制初始化 6.聚合初始化 7.列表初始化 C++类型大致分为: 标量: int; float; char; bool; enum; void,nullptr_t; 指针;引用 复合体:数组;union;...
  • C++11_列表初始化初始化

    千次阅读 2021-01-25 17:00:37
    C++11,集合(列表)的初始化已经成为C++语言的一个基本功能,这种初始化的方法被称为“初始化列表”(initializer list),例如: #include <vector> #include <map> using namespace std; int a[]...
  • C++中类中静态变量在类外初始化

    千次阅读 2020-08-02 15:32:59
    我们知道C++类的静态成员变量是需要初始化的,但为什么要初始化呢。 其实这句话“静态成员变量是需要初始化的”是有一定问题的,应该说“静态成员变量需要定义”才是准确的,而不是初始化。 两者的区别在于:初始化...
  • 一、类中嵌套结构或声明 在类中嵌套结构或声明,可以使其作用域为整个。可以使用嵌套的结构或来声明成员,也可以将它作为方法 的类型名称,但只能在类中使用。可以查看如下示例代码: typedef ...
  • C++类成员初始化顺序问题

    万次阅读 多人点赞 2017-11-22 21:08:20
    今天刚把买了一个月的剑指offer这本书翻阅一下,看到一个简单的举例。...C++类成员初始化顺序问题1 C++类成员初始化顺序问题2 问题来源: 由于面试题,考官出了一道简单的程序输出结果值的题:如下,#include us
  • C++全局变量的初始化过程

    千次阅读 2019-09-29 09:40:33
    全局变量在main()前完成...如果一个项目,多个dll都用到一个全局变量在共同的lib,则每个dll都有一个独立的全局变量(地址不同),每个全局变量会初始化。 如下代码,A里面访问了全局变量g_b, 改变全局变量g_a...
  • C++之列表初始化详解

    千次阅读 2022-04-11 16:40:04
    详细介绍列表初始化适用于哪些场景以及列表初始化所具有的优点,每个观点均有详细的代码验证,方便理解!
  • c++的声明中初始化私有成员变量 之前的学习都没有做博客记录一下,心血来潮想试一下,记录一下自己的学习历程,方便自己复习,大家见笑了。 这个做法是突然想到,查了一下确实允许这样的做法,自己随便写的...
  • c++中初始化列表详解

    万次阅读 多人点赞 2018-05-18 18:15:04
    与其他函数不同,构造函数除了有名字,参数列表和函数体之外,还可以有初始化列表,初始化列表以冒号开头,后跟一系列以逗号分隔的初始化字段。 class foo { public: foo(string s, int i):name(s), id(i){} ; //...
  • C++中类中类的静态变量初始化

    千次阅读 2020-05-02 22:56:38
    关于C++中类中类的静态变量,或者说类中结构体中的静态变量的初始化问题,解释如下: 1.首先,定义在结构体或者类中的变量,在头文件中定义时仅仅是一个声明,并未分配空间,只有在静态变量被初始化之后才分配空间...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 672,977
精华内容 269,190
关键字:

c++类中初始化