精华内容
下载资源
问答
  • C++11初始化列表与参数列表的作用

    千次阅读 2016-12-20 16:18:18
    对于构造函数而言,初始化列表作用无非是在对成员变量申请内存时进行初始化。执行构造函数时,先执行初始化表的内容,若初始化里面里面没有数据,侧编译器安装系统默认的方式对成员变量申请内存,进行系统默认的...

    最近遇到了一个程序,一开始有些莫名其妙,最后经过思考、猜想、验证的过程,将其总结如下:

    首先先上代码:

    函数声明如下:

    class Controller
    {
        using AnalysisManager   = NST::analysis::AnalysisManager;
        using FiltrationManager = NST::filtration::FiltrationManager;
    
        class Running
        {
        public:
            inline Running(Controller&);
            Running()               = delete;
            Running(const Running&) = delete;
            Running& operator=(const Running&) = delete;
            inline ~Running();
    
        private:
            Controller& controller;
        };
    
    public:
        Controller(const Parameters&);
        Controller(const Controller&) = delete;
        Controller& operator=(const Controller&) = delete;
        ~Controller();
    
        int run();
    
    private:
        // initializer for global outptut
        utils::Out::Global gout;
        // initializer for global logger
        utils::Log::Global glog;
    
        // storage for exceptions
        RunningStatus status;
    
        // signal handler
        SignalHandler signals;
    
        // controller subsystems
        std::unique_ptr<AnalysisManager>   analysis;
        std::unique_ptr<FiltrationManager> filtration;
    };

    只看其构造函数:

    Controller::Controller(const Parameters& params) try
        : gout       {utils::Out::Level(params.verbose_level())}
        , glog       {params.log_path()}
        , signals    {status}
        , analysis   {}
        , filtration {new FiltrationManager{status}}
    {
        // clang-format on
        switch(params.running_mode())
        {
        case RunningMode::Profiling:
        {
            analysis.reset(new AnalysisManager{status, params});
            if(analysis->isSilent())
                utils::Out::Global::set_level(utils::Out::Level::Silent);
    
            filtration->add_online_analysis(params, analysis->get_queue());
        }
        break;
        case RunningMode::Dumping:
        {
            filtration->add_online_dumping(params);
        }
        break;
        case RunningMode::Analysis:
        {
            analysis.reset(new AnalysisManager{status, params});
            if(analysis->isSilent())
                utils::Out::Global::set_level(utils::Out::Level::Silent);
    
            filtration->add_offline_analysis(params.input_file(),
                                             analysis->get_queue());
        }
        break;
        case RunningMode::Draining:
        {
            filtration->add_offline_dumping(params);
        }
        break;
        }
        droproot(params.dropuser());
    }

    对于上述的构造函数,涉及到的几个知识点总结如下:

    一:C++11特性初始化参数列表

    C++11引入了一个新的初始化方式,称为初始化列表(List Initialize),具体的初始化方式如下:

    int i = {1};
    int j{3};

    初始化列表在使用的时候有如下一些要求:

    1. 当初始化内置基本类型的时候,列表初始化不允许出现隐式类型的转换,例如:

    long double ld = 3.1415926536;
    int a{ld}, b = {ld}; //出错,不允许出现精度的丢失
    int c(ld), d = ld; // 非列表初始化,但是会出现精度的丢失

    2. 初始化列表可以用于初始化结构体类型,例如:

    #include <iostream>
    
    struct Person
    {
      std::string name;
      int age;
    };
    
    int main()
    {
    	Person p = {"Frank", 25};
    	std::cout << p.name << " : " << p.age << std::endl;
    }

    3. 其他一些不方便初始化的地方使用,比如std<vector>的初始化,如果不使用这种方式,只能用构造函数来初始化,难以达到效果:

    	std::vector<int> ivec1(3, 5);
    	std::vector<int> ivec2 = {5, 5, 5};
    	std::vector<int> ivec3 = {1,2,3,4,5}; //不使用列表初始化用构造函数难以实现

    二:初始化列表的作用

    对于构造函数而言,初始化列表的作用无非是在对成员变量申请内存时进行初始化。执行构造函数时,先执行初始化表的内容,若初始化里面里面没有数据,侧编译器安装系统默认的方式对成员变量申请内存,进行系统默认的方式赋值,随后再进行构造函数中花括号内部的指令。

    A.对于引用型成员变量和const常量型成员变量,则必须通过初始化表初始化该成员变量。
    B.如果有类类型成员变量,而该类型又没有无参构造函数,则必须通过初始化表初始化该成员变量。
    C.需要在子类中指定其基类部分的初始化方式,必须使用初始化表。
    D.成员变量初始化顺序有声明顺序决定,而与初始化表的顺序无关。
    E.对于参数列表中所列的成员变量,可以不包含所有的成员变量。

    三:delete的作用

    为了能够显式的禁用某个函数,C++11 标准引入了一个新特性:deleted 函数。程序员只需在函数声明后加上“=delete;”,就可将该函数禁用。类 X 的拷贝构造函数以及拷贝赋值操作符声明为 deleted 函数,就可以禁止类 X 对象之间的拷贝和赋值




    
    
    展开全文
  • 构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。例如: class CExample { public: int a; float b; //构造函数初始化列表 CExample(): a(0),b...

    部分内容来自百度知道!!

    构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。例如:
    class CExample {
    public:
    int a;
    float b;
    //构造函数初始化列表
    CExample(): a(0),b(8.8)
    {}
    //构造函数内部赋值
    CExample()
    {
    a=0;
    b=8.8;
    }
    };
    上面的例子中两个构造函数的结果是一样的。

    上面的构造函数(使用初始化列表的构造函数)显式的初始化类的成员;而没使用初始化列表的构造函数是对类的成员赋值,并没有进行显式的初始化。
    初始化和赋值对内置类型(就是基本数据类型)的成员没有什么大的区别,像上面的任一个构造函数都可以。

    对非内置类型成员变量,为了避免两次构造,推荐使用类构造函数初始化列表。

    为什么对非内置类型成员变量,不适用类构造函数初始化列表就会有两次构造呢?

    看下边的例子:

    class B{
    public:
    	B()
    	{
    		cout << "B:B() is called" << endl;
    	}
    	B(int x)
    	{
    		cout << "B:B(x) is called" << endl;
    		x = a;
    	}
    private:
    	int a;
    };
    class A{
    public:
    	A(int x)
    	{
    		a = x;
    		b = B(x);
    		cout << "A:A() is called" << endl;
    	}
    	~A()
    	{
    
    	}
    private:
    	int a;
    	B b;
    };
    int main()  
    {  
    	A t(1);
    	system("pause");
    	return 0;  
    }  
    输出:B:B() is called

              B:B(x) is called

              A:A() is called
    但如果把类A里的构造函数改成

    A(int x):a(x),b(B(x)){}
    就输出:B:B(x) is called.

    其实说这么多就是说明,当一个类中有非内置类型成员变量时,若没有显示初始化这个非内置类型成员变量,那么编译器会隐士调用该非内置类型成员变量的默认构造函数,而如果用了成员初始化构造函数,对这个变量有了显示初始化,系统就不会再隐士调用它的默认构造函数了,所以这里少了一次构造。

    但有的时候必须用带有初始化列表的构造函数:
    1.成员类型是没有默认构造函数的类。若没有提供显示初始化式,则编译器隐式使用成员类型的默认构造函数,若类没有默认构造函数,则编译器尝试使用默认构造函数将会失败。
    2.const成员或引用类型的成员。因为const对象或引用类型只能初始化,不能对他们赋值。

    class B{
    public:
    	B()
    	{
    		cout << "B:B() is called" << endl;
    	}
    	B(int x)
    	{
    		x = a;
    	}
    private:
    	int a;
    };
    class A{
    public:
    	A()
    	{
    		cout << "A:A() is called" << endl;
    	}
    	~A()
    	{
    
    	}
    private:
    	int a;
    	B b;
    };
    int main()  
    {  
    	A t;
    	system("pause");
    	return 0;  
    } 
    输出:B:B() is called

               A:A() is called

    我们看到在类A里边有非内置类型成员变量b,在调用A的构造函数时,我们没有显示初始化b,但系统会隐士调用成员类型(这里是b)的默认构造函数
    。如果类B没有默认构造函数,则编译器会失败。所以在这种情况下,必须使用初始化列表的构造函数。

     
    初始化数据成员与对数据成员赋值的含义是什么?有什么区别?
    首先把数据成员按类型分类并分情况说明:
    1.内置数据类型,复合类型(指针,引用)
    在成员初始化列表和构造函数体内进行,在性能和结果上都是一样的
    2.用户定义类型(类类型)
    结果上相同,但是性能上存在很大的差别。因为类类型的数据成员对象在进入函数体前已经构造完成,也就是说在成员初始化列表处进行构造对象的工作,调用构造函数,在进入函数体之后,进行的是对已经构造好的类对象的赋值,又调用个拷贝赋值操作符才能完成(如果并未提供,则使用编译器提供的默认按成员赋值行为)
    Note:
    初始化列表的成员初始化顺序:
    C++初始化类成员时,是按照声明的顺序初始化的,而不是按照出现在初始化列表中的顺序。
    Example:
    class CMyClass {
    CMyClass(int x, int y);
    int m_x;
    int m_y;
    };
    CMyClass::CMyClass(int x, int y) : m_y(y), m_x(m_y)
    {
    }
    你可能以为上面的代码将会首先做m_y=I,然后做m_x=m_y,最后它们有相同的值。但是编译器先初始化m_x,然后是m_y,,因为它们是按这样的顺序声明的。结果是m_x将有一个不可预测的值。有两种方法避免它,一个是总是按照你希望它们被初始化的顺序声明成员,第二个是,如果你决定使用初始化列表,总是按照它们声明的顺序罗列这些成员。这将有助于消除混淆。

    展开全文
  • 初始化列表作用

    千次阅读 2014-08-23 18:34:58
    冒号这种初始化方法,也叫做,初始化列表,也就是变量初始化的时候调用的 意味着,在一个类当中,一个成员变量只能在初始化赋值。 比如: const, 比如引用&。 举个例子: class A { public: A()

    我纠结的问题都在primer上有很好的解答


    之前突然想到,为什么要存在冒号这种初始化方法,在google被墙,没办法只能求助于度娘。。。


    冒号这种初始化方法,也叫做,初始化列表,也就是变量初始化的时候调用的

    意味着,在一个类当中,一个成员变量只能在初始化赋值。

    比如: const, 比如引用&。


    举个例子:

    class A
    {
    public:
       A(i)
       {
            a = i;
            b = i;
            c = i;
       }
    
    private:
       int a;
       const int b;
       int &c;
    };

    这样是不合法的, 因为b, c只能在初始化时赋值。


    所以,只能如此初始化:

    class A
    {
    public:
       A(int i):a(i), b(i), c(i){}
    
    private:
       int a;
       const int b;
       int &c;
    };


    还有一个比较重要的问题,就是初始化列表的初始化顺序是怎样的?

    class A
    {
    public:
    	A():b(a-1), a(b-1)
    	{
    		cout<<b<<endl;
    		cout<<a<<endl;
    	};
    
    private:
    	int a;
    	int b;
    };
    
    也就是说,a和b的值分别是多少?

    1
    -858993461

    答案就是,初始化列表里的顺序,与初始化顺序无关

    这里首先定义的是a,所以a先初始化为b - 1即 -858993460 - 1,-858993461

    而b是第二个定义的,所以后初始化b为a- 1即-858993461,为-858993462


    如果,没有必要的情况下,还是少用初始化列表,尽量在构造函数中顺序的定义。



    展开全文
  • c++中构造函数有初始化列表

    c++中构造函数有初始化列表,目的是用于变量的初始化。

     

    百度初始化列表会告诉你初始化列表能够提高构造函数的性能,在派生类中可以跳过基类构造函数,直接进行赋值操作。下面是一常见派生类中使用初始化列表的例子。

    class A
    {
    public:
    A(int i = 0):a(i){} //基类初始化成员变量
    protected:
    int a;
    };
    class B :public A
    {
    public:
    B():a(5){}//派生类不能初始化基类成员变量
    };
    
    这样是正确的:
    #include<iostream>
    usingnamespace std;
    class A
    {
    protected:
    int a;
    public:
    A(int i = 0):a(i) {}
    };
    
    
    class B :public A
    {
    public:
    B():A(5){}//基类的成员函数
    void printinfo()
    {
    cout<< a<< endl;
    }
    };
    
    也可以这样:
    #include<iostream>
    usingnamespace std;
    class A
    {
    public:
    A(int i = 0):a(i) {}
    protected:
    int a;
    };
    
    
    class B :publicA
    {
    public: 
    B() {a=5;}
    };
    

     

    其中为什么要使用初始化列表是因为:

    1.常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面;
    2.引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表里面
    3. 没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化。
     
    另外一个重点问题是:成员是按照他们在类中出现的顺序进行初始化的,而不是按照他们在初始化列表出现的顺序初始化的。
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class base
    {
    private:
    	int m_i;
    	int m_j;
    public:
    	base(int i): m_j(i), m_i(m_j){}//这里改变顺序
    	base():m_j(0),m_i(m_j){}
    	int get_i()
    	{
    		return m_i;
    	}
    	int get_j()
    	{
    		return m_j;
    	}
    };
    class A
    {
    	static const int size=0;//静态,常量,整型才可以直接初始化。其他都不可以。
    };
    
    int main(int argc, char* argv)
    {
    	base obj(98);
    	cout<<obj.get_i()<<endl<<obj.get_j()<<endl;
    	base nn;
    	cout<<nn.get_i()<<endl<<nn.get_j()<<endl;
    
    	A nb;
    
    	return 0;
    }

    这里就有一个有趣的问题,虽然m_j出现在m_i前面,但m_i在m_j前面定义,所以先初始化m_i,此时m_j还是随机数,所以m_i就被初始化为一个随机数。
    建议:按照成员的定义顺序进行初始化!

     

    展开全文
  • C++构造函数的初始化列表

    千次阅读 2018-12-05 17:30:41
    构造函数的初始化列表 当一个类的成员变量是另一个类的对象时 例: #include&lt;iostream&gt; using namespace std; class A{ public: A() { cout&lt;&lt;"A()"&lt;&lt;endl;...
  • c++11:就地初始化列表初始化

    千次阅读 2019-09-15 20:03:58
    选自: https://blog.csdn.net/K346K346/article/details/55194246 https://www.cnblogs.com/lsgxeva/p/7787245.html 还可以看看: ... 1.就地初始化 1.1简...
  • 初始化时使用作用域操作符来指出静态成员所属的类.但如果静态成员是整型或是枚举型const,则可以在类声明中初始化!!! 代码如下:#include <iostream>using namespace std;class test{public:static int num;};int test...
  • 类的构造函数的作用是对其成员进行初始化。而在构造函数中可以使用初始值列表为新创建的对象的成员进行赋值。 1 初始值列表 在类的构造函数名之后紧跟着冒号,冒号后面是要初始化的成员名,之后是圆括号或者花括号...
  • C++使用初始化列表初始化数据成员的三种情况

    万次阅读 多人点赞 2018-08-11 15:04:27
    类对象的构造顺序是这样的: 1.分配内存,调用构造函数时,隐式/...使用初始化列表有两个原因: 原因1.必须这样做: 《C++ Primer》中提到在以下三种情况下需要使用初始化成员列表: 情况一、需要初始化的数据...
  • 构造函数与初始化列表

    万次阅读 多人点赞 2018-08-01 18:17:33
    0.初始化与赋值的区别 意义上: 1)初始化:一个变量或者一个对象在产生的时候就赋予一个值,属于伴随性质 2)赋值:在一个变量或者一个对象在产生之后的任意时刻赋予一个值,属于任意性质 宏观代码上: 1)...
  • C++11中,集合(列表)的初始化已经成为C++语言的一个基本功能,这种初始化的方法被称为“初始化列表”(initializer list),例如: #include <vector> #include <map> using namespace std; int a[]...
  • 列表初始化

    2018-04-20 19:02:44
    在c++98/03里有很多的对象初始化的方法:int i_arr[3]={1,2,3}; //数组 struct A{  int x;  struct B{ int i,j;  }b; }a={1,{2,3}}; //POD类型 //拷贝初始化 int i=0; class Foo{ public:  Foo(int){...
  • 先总结下:由于类成员初始化总在构造函数执行之前1)从必要性: a. 成员是类或结构,且构造函数带参数:成员初始化时无法调用缺省(无参)构造函数 b. 成员是常量或引用:成员无法赋值,只能被...仅在初始化列表里...
  • C++11 列表初始化(list_initialization)

    千次阅读 2019-04-29 09:12:35
    列表初始化 定义:从花括号初始化列表初始化对象。 语法: // 直接列表初始化 T object { arg1, arg2, ... }; (1) T { arg1, arg2, ... } (2) new T { arg1, arg2, ... } (3) Class { T member { arg1, arg...
  • 简述C++类继承的关系,运用过程中涉及到的初始化列表,类内部使用其他类等。
  • C++11 列表初始化

    千次阅读 2020-02-15 15:12:59
    C++11之前主要有以下几种初始化方式: //小括号初始化 string str("hello");...//POD对象与POD数组列表初始化 struct Studnet { char* name; int age; }; Studnet s={"dablelv",18}; //纯数据(Plain of Data,PO...
  • 列表初始化 (C++11 起)   C++   C++ 语言   初始化   从花括号初始化列表初始化对象 语法 直接列表初始化   T object { arg1, arg2, ... }; (1)     T { arg1, arg2, ... }...
  • 一、成员变量初始化列表 与其他函数不同,构造函数除了有名字,参数列表和函数体之外,还可以有初始化列表初始化列表以冒号开头,后跟一系列以逗号分隔的初始化字段。 class foo { public: foo(string s, int i)...
  • 子类的初始化列表,只能对子类的成员变量进行初始化,也就是Derived::x(自己类的作用域),所以报子类无该变量的错误。 因为首先调用了父类的默认构造方法,在这之前,执行父类的初始化列表对x进行了初始化,如果...
  • C++11新特性之列表初始化

    万次阅读 多人点赞 2017-01-04 15:11:31
    在我们实际编程中,我们经常会碰到变量初始化的问题,对于不同的变量初始化的手段...这些不同的初始化方法都有各自的适用范围和作用,且对于类来说不能用这种初始化的方法,最主要的是没有一种可以通用的初始化方法适用
  • C++11 就地初始化列表初始化

    万次阅读 2017-02-15 14:12:56
    C++11之前,C++主要有以下几种初始化方式://小括号初始化 string str(&amp;amp;quot;hello&amp;amp;quot;);//等号初始化 string str=&amp;amp;quot;hello&amp;amp;quot;;//大括号初始化 struct ...
  • C++构造函数初始化列表

    万次阅读 2018-02-07 19:52:47
    何为构造函数初始化列表 class Sample { public: // 构造函数内部赋值 Sample(int a) { a_ = a; } // 构造函数初始化列表 Sample(int a) : a_(a) { } private: int a_; }; 上面的代码中,Sample类的2...
  • nodejs初始化

    千次阅读 2019-06-20 11:22:22
    nodejs初始化的文章相当的多,多看几篇文章基本就可以大体了解了。如果要从代码角度入手,我这里推一篇文章写的比较细 https://yq.aliyun.com/articles/682681?spm=a2c4e.11155472.0.0.2fcf777bSSoRJ2 这篇文章...
  • 第一次是由于继承了B3,虽然在C的构造函数的初始化列表里你没看到B3(x)或者B3(),但并不代表B3的构造函数没有在发挥作用。事实上,B3被隐性初始化了,因为B3的构造函数没有参数,所以写不写B3()都无所谓,这里恰好...
  • 1)首先是初始化列表作用 初始化列表其实是一种 后天强加 的初始化语义。 编译器处理后,会把初始化列表的内容先 转化 ,然后插入到构造函数的开头,之后的内容才是你在构造函数里写的语句,如果你有写的话。 但是...
  • 关于类的构造函数,可以分为两个部分,初始化部分(初始化列表)和计算部分(花括号间的赋值运算),在花括号作用域间进行的运算不是初始化,而是赋值。     对于必须在定义时初始化的情况在类构造函数中也是...
  • C++类和对象(下)——初始化列表、static成员和友元

    千次阅读 热门讨论 2021-03-08 09:23:18
    C++类和对象——初始化列表、static成员和友元一、再谈构造函数1.1 构造函数整体赋值1.2 初始化列表三级目录 关于C++类和对象的学习 C++类和对象(上)——类的基本概念、类的限定符及封装和类成员函数的this指针 C++...
  • C++11--可以这么玩初始化列表吗?

    万次阅读 2016-07-06 00:13:13
    我们知道C++11新增了初始化列表,在之前的博客中也有过介绍。 浅析C++中的初始化列表(区别赋值和初始化) c++11特性之initializer_list今天就讨论这么用初始化列表,不喜勿喷。先写一个类:class SimpleType { ...
  • C++成员初始化列表作用

    千次阅读 2010-01-13 11:27:00
    转帖:http://blog.chinaunix.net/u2/75321/showart_1161692.html 好文:高质量程序设计指南-知识点精选 http://www.cnblogs.com/JCSU/articles/1083052.html 摘要:(1) 区别“赋值” 和 “初始化”这两个概念...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 350,415
精华内容 140,166
关键字:

初始化列表的作用