精华内容
下载资源
问答
  • c++类内初始化
    千次阅读
    2020-09-22 12:18:56

    类的构造函数的作用是对其成员进行初始化。而在构造函数中可以使用初始值列表为新创建的对象的成员进行赋值。

    1 初始值列表

    在类的构造函数名之后紧跟着冒号,冒号后面是要初始化的成员名,之后是圆括号或者花括号括起来的初始值。这样的结构就是构造函数的初始值列表,如下所示。

    class A
    {
      public:
        A() :a(1),b(2) {};
        int a;
        int b;
    };

    其中,自定义类A具有一个包含了初始值列表的构造函数,使用该构造函数创建对象时,该对象的成员变量a的值是1,b的值是2。

    2 类内初始化

    对于“1 初始值列表”中提到的自定义类A,如果其还存在多个构造函数,

    A(int i) :a(1),b(2) {};
    A(int i, int j) :a(1),b(2) {};
    A(int i, int j, int z) :a(1),b(2) {};

    多个构造函数都包含了相同的初始值列表,代码看上去有些冗长。此时可以使用类内初始化的方法对其进行简化。

    类内初始化指的是在定义类的成员时对其赋初值,赋初值的方式有两种:使用等号赋值和使用大括号赋值。

    class A
    {
    
    public:
    .....
    
      int a = 1;
      int b{ 2 };
    };

    此时,对于之前提到的包含初始值列表的构造函数,就可以简写成如下格式

    A(){};
    A(int i) {};
    A(int i, int j){};
    A(int i, int j, int z)  {};

    之后无论使用哪一种构造方法来产生该类的对象,这个对象的a和b的值分别是1和2。需要注意的是,类内初始化是C++11的新属性

    更多相关内容
  • 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++类成员变量初始化详解

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

    1.类初始化顺序

    当类初始化的时候,会调用其构造函数并进行初始化。当对象结束其生命周期,会调用析构函数进行资源回收。

    注意类在调用资深构造函数之前,首先会调用其成员变量构造函数并进行初始化,再进入自身构造函数进行初始化。成员变量的声明顺序,就是初始化顺序。后面我们提到的很多情况就跟这个有关系,后面再进行详细解读。

    2.声明时初始化

    第一种方式是在成员变量声明时初始化。可以看如下示例。

    class D {
        int a = 10;
    };
    

    在声明变量a的时候即给其初始化为10。不过注意这种写法是c++11以后才有的。上述代码在IDE中会有如下警告信息:

    in-class initialization of non-static data member is a C++11 extension [-Wc++11-extensions]
    

    3.构造函数初始化列表

    第二种方式是在构造函数中加入一个初始化列表,对成员变量进行初始化。

    class D {
        int a, b;
        string c;
        public:
            D() : a(1), b(2), c("sss") {
                cout<<"a is: "<<a<<endl;
                cout<<"b is: "<<b<<endl;
                cout<<"c is: "<<c<<endl;
            }
    };
    

    如果我们对D进行实例化,

    int main(int argc, char const *argv[])
    {
        D d;
        return 0;
    }
    

    代码会有如下输出

    a is: 1
    b is: 2
    c is: sss
    

    4.构造函数内部赋值

    在其他语言中,比如java,最常用的方式为在构造函数内部赋值。

    class D {
        int a, b;
        string c;
        public:
            D(int a, int b, string c) {
                this->a = a;
                this->b = b;
                this->c = c;
                cout<<"a is: "<<a<<endl;
                cout<<"b is: "<<b<<endl;
                cout<<"c is: "<<c<<endl;
            }
    };
    
    int main(int argc, char const *argv[])
    {
        D d(1, 2, "sss");
        return 0;
    }
    

    上面代码输出为

    a is: 1
    b is: 2
    c is: sss
    

    5.只能构造函数初始化列表的情况

    如果一个类成员,他本身是一个类或者结构,而且这个类成员没有默认的无参构造函数,只有带参数的构造函数,这个时候对类成员初始化时,必须调用类成员带参数的构造函数。如果再初始化列表中没有完成类成员初始化,代码会报错。

    };
    
    class F {
        E e;
        public:
            F() {cout<<"init F class!"<<endl;}
    };
    
    int main(int argc, char const *argv[])
    {
        F f;
        return 0;
    }
    

    上述代码是可以正常运行的,因为类E有默认无参构造函数。

    而如果将代码改为下面的样子,给E加一个带参数的构造函数

    class E {
        int num;
        public:
            E(int n) {
                this->num = n;
            }
    };
    
    class F {
        E e;
        public:
            F() {cout<<"init F class!"<<endl;}
    };
    
    int main(int argc, char const *argv[])
    {
        F f;
        return 0;
    }
    

    上面代码在IDE里直接会报错:

    constructor for 'F' must explicitly initialize the member 'e' which does not have a default constructor
    

    此时需要将F的构造函数改成如下形式:

    class F {
        E e;
        public:
            F() : e(10) {cout<<"init F class!"<<endl;}
    };
    

    另外,如果类的成员变量中有const时候,也需要在成员初始化列表中赋值完成初始化。

    class F {
        private:
            const int num;
        public:
            F(): num(10) {}
    };
    

    比如上面类F中有一个const常量num,就需要再F构造函数列表中对其进行赋值,否则代码会报错。

    6.列表初始化与构造函数初始化区别

    当采用列表初始化的时候,代码直接调用了成员变量的构造函数,只需要一步就可以完成。
    而在构造函数中初始化的时候,先调用的是成员变量的默认构造函数构造了类成员,然后再调用赋值运算符对之前默认构造的类成员进行赋值,这实际上进行了两步操作。
    当类的结构较为复杂的时候,会存在性能上的差异。

    展开全文
  • C++学习——初始化

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

    1.类通过构造函数进行数据成员初始化

    一般来说,类中的数据成员是私有的,不能通过对象共有访问的方式对数据成员赋初始值。一般来说,构造函数就是用来用来在创建对象时初始化对象, 为对象数据成员赋初始值。
    构造函数是类的一种特殊成员函数,不需要人为调用,而是在建立对象时自动被执行。

    2.类成员初始化方式?

    赋值初始化,通过在函数体内进行赋值初始化;
    列表初始化,在冒号后使用初始化列表进行初始化。
    
    这两种方式的主要区别在于:
    
    对于在函数体中初始化,是在所有的数据成员被分配内存空间后才进行的。
    
    列表初始化是给数据成员分配内存空间时就进行初始化,
    就是说分配一个数据成员只要冒号后有此数据成员的赋值表达式(此表达式必须是括号赋值表达式),
    那么分配了内存空间后在进入函数体之前给数据成员赋值,
    就是说初始化这个数据成员此时函数体还未执行。 
    

    列表初始化:

    #include<iostream>
    using namespace std;
    
    class solution {
    public:
        solution(int value1,int value2):a(value1),b(value2){}//列表初始化
        void print() {
            cout << "a=" << a << " " << "b=" << b << endl;
        }
    private:
        int a;
        int b;
    };
    int main()
    {
        solution s(1, 2);
        s.print();
        return 0;
    }
    

    赋值初始化:

    #include<iostream>
    using namespace std;
    
    class solution {
    public:
        solution(int value1,int value2){
            a = value1;
            b = value2;
        }//列表初始化
        void print() {
            cout << "a=" << a << " " << "b=" << b << endl;
        }
    private:
        int a;
        int b;
    };
    int main()
    {
        solution s(1, 2);
        s.print();
        return 0;
    }
    
    a=1 b=2
    

    3.什么情况下必须使用列表初始化?

    必须使用成员初始化的四种情况:

    	当初始化一个引用成员时;
    	当初始化一个常量成员时;
    	当调用一个基类的构造函数,而它拥有一组参数时;
    	当调用一个成员类的构造函数,而它拥有一组参数时;
    
    #include<iostream>
    using namespace std;
    
    class solution {
    public:
        solution(int& value1,int value2):a(value1),b(value2){
        }//正确,列表初始化
        /*solution(int& value1, int value2) {
            a = value1;
            b = value2;
        }//错误,赋值初始化*/
        void print() {
            cout << "a=" << a << " " << "b=" << b << endl;
        }
    private:
        int& a;
        int b;
    };
    int main()
    {
        int a = 1;
        solution s(a, 2);
        s.print();
        return 0;
    }
    

    4.为什么用列表初始化成员变量会快一些?

    赋值初始化是在构造函数当中做赋值的操作,而列表初始化是做纯粹的初始化操作。我们都知道,C++的赋值操作是会产生临时对象的。临时对象的出现会降低程序的效率。

    5.派生类构造函数的执行顺序

    虚拟基类的构造函数(多个虚拟基类则按照继承的顺序执行构造函数)。
    
    基类的构造函数(多个普通基类也按照继承的顺序执行构造函数)。
    
    类类型的成员对象的构造函数(按照初始化顺序)
    
    派生类自己的构造函数。
    
    #include<iostream>
    using namespace std;
    
    //虚基类
    class A {
    public:
        A(int value) :a(value) {
            cout << "A的初始化" << endl;
        }
    private:
        int a;
    };
    
    //基类
    class B {
    public:
        B(int value) :b(value) {
            cout << "B的初始化" << endl;
        }
    private:
        int b;
    };
    
    //类类型的成员
    class C {
    public:
        C() {
            cout << "C的初始化" << endl;
        }
    };
    
    //派生类
    class D:public B,virtual public A {
    public:
        D(int value1, int value2) :B(value1), A(value2) {//初始化顺序和初始化列表的顺序无关,构造函数的初始化顺序按照一定规则进行。
            cout << "D的初始化" << endl;
        }
    private:
        C c;
    };
    int main()
    {
        D d(1, 2);
        return 0;
    }
    
    A的初始化
    B的初始化
    C的初始化
    D的初始化
    
    展开全文
  • 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++类成员初始化方式

    万次阅读 多人点赞 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-06-06 16:14:32
    初始化列表是中构造函数的一部分,用于实例化中变量时 赋初值。
  • C++11_列表初始化类内初始化

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

    千次阅读 2019-06-14 17:04:11
    1.c++变量的初始化方式 首先把需要初始化的成员变量分为几: a.一般变量(int) b.静态成员变量(static int) c.常量(const int) d.静态常量(static const int) 对应的初始化方式是: a.一般变量可以...
  • C++初始化

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

    千次阅读 2019-09-18 15:14:54
    C++11,我么可以为类内成员变量提供一个初始值,则我们在创建对象的时候,这个初始值就用来初始化该成员变量。 enum LineStyle{ lsSolid, lsDash, lsDot, }; class Rect { public: Rect() :left{0}, top{...
  • C++类指针初始化

    千次阅读 2017-12-29 14:22:17
    C++ 指针定义的时候没有初始化的时候,居然可以安全的调用内部的成员函数而不出错。 在网上查了一下: 初始化为NULL的指针可以安全的调用不涉及成员变量的成员函数而不出错,但是如果成员函数中...
  • 一开始,我其实不打算把初始化列表单独拿出来写一篇文章的,我打算在创建一个的那一篇文章里一起写掉,但是写着写着就发现事情没有我想的那么简单,这里面的内容还是比较多地。 二、初始化列表格式: 在构造函数...
  • C++的静态变量初始化

    千次阅读 2020-05-02 22:56:38
    关于C++的静态变量,或者说中结构体中的静态变量的初始化问题,解释如下: 1.首先,定义在结构体或者中的变量,在头文件中定义时仅仅是一个声明,并未分配空间,只有在静态变量被初始化之后才分配空间...
  •   在C++Primer 中文版(第5版)第270页中,对静态数据成员的类内初始化作如下说明: 我们可以为静态成员提供const整数类型的类内初始值,不过要求静态成员必须是字面值常量类型的constexpr。   上面的句子不好...
  • C++ 对象的初始化

    千次阅读 2021-04-13 20:50:08
    对象的初始化 序: 程序在使用时是常常需要对变量进行初始化赋值。与c语言不同,在面向对象的编程中,使用构造函数对数据成员进行初始化,有多种方式。 录: 一、无参数的构造函数 二、带参数的构造函数 三、使用...
  • c++中的初始化列表

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

    千次阅读 2017-12-28 16:35:15
    C++初始化有很多方式:默认初始化,值初始化,直接初始化,拷贝初始化,列表初始化。这些方式之间有什么区别与联系呢?我们一一来看。 1.默认初始化默认初始化是指定义变量时没有指定初值时进行的初始化操作。例如...
  • C++类成员初始化顺序问题

    万次阅读 多人点赞 2017-11-22 21:08:20
    今天刚把买了一个月的剑指offer这本书翻阅一下,看到一个简单的举例。...C++类成员初始化顺序问题1 C++类成员初始化顺序问题2 问题来源: 由于面试题中,考官出了一道简单的程序输出结果值的题:如下,#include us
  • 摘要:在C++11之后,声明时初始化->初始化列表->构造函数初始化
  • C++之列表初始化详解

    千次阅读 2022-04-11 16:40:04
    详细介绍列表初始化适用于哪些场景以及列表初始化所具有的优点,每个观点均有详细的代码验证,方便理解!
  • C++类中成员变量的初始化有两种方式: 构造函数初始化列表和构造函数体内赋值。下面看看两种方式有何不同。 成员变量初始化的顺序是按照在那种定义的顺序。1、内部数据类型(char,int……指针等)[cpp] view ...
  • C++构造函数初始化类对象

    万次阅读 多人点赞 2019-04-12 15:53:51
    文章目录一.构造函数二.构造函数的分类三.构造函数的写法 ...【5】构造函数通常用于对类内的数据进行初始化。 二.构造函数的分类 无参的构造函数 有参的构造函数 参数初始化表的构造函数【重点】 ...
  • C++显式初始化类成员

    千次阅读 2019-03-10 19:15:58
    对于没有定义构造函数,且全体数据成员为public的,可以使用显式初始化。 class A { public: char *str; int i; } int main() { A a={"One",1}; } 上面这种,只能使用显式初始化,使用这种...
  • 首先,应该明确需要定义,但不是真实存在的对象,的定义过程是对的一个“声明”,并不会为其分配内存(包括static成员,也因此static成员必须类内声明,外定义(初始化))。 必须通过构造函数才能将...
  • C++类成员的初始化顺序

    千次阅读 2019-08-10 14:46:48
    C++中变量的初始化顺序应该是: 1 基类的静态变量或全局变量 2 派生的静态变量或全局变量 3 基类的成员变量 4 派生的成员变量 注意,对于一个中的变量,初始化的顺序并不是按照初始化成员列表的顺序进行...
  • C++: 数组初始化

    千次阅读 2021-04-25 21:24:56
    通过如下代码初始化一个数组,初始化的规则就是不足数组大小的按默认值补位 int a[5]; //int默认0 int b[5] = {1,2}; // {1,2,0,0,0} 不足5位的0补位 string c[5] = {"a", "b"}; // {"a","b","","",""} 如果不明确...
  • C++ 初始化方式

    千次阅读 2022-04-25 17:15:40
    C++语言中,初始化和赋值... 下表为string的各种初始化方式[引自:C++ Primer (第五版)]: 1. 默认初始化 表中string的第一种初始化方式称为默认初始化,用户没有给string实例s1一个初值,s1将是一个...
  • C++中的初始化

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

空空如也

空空如也

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

c++类内初始化