服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++类成员初始化的三种方式

C++类成员初始化的三种方式

2022-01-17 14:16我是一颗大西瓜 C/C++

如果静态成员不满足常量性,则不可以就地声明,而且即使常量的静态成员也只能是整型或者枚举型才能就地初始化。而非静态成员变量的初始化则必须在构造函数中进行。首先,先得了解一下C++支持哪几种类成员初始化的方式,

前言:

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

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

一、初始化方式

1、初始化方式一:初始化列表

?
1
2
3
4
5
6
class A
{
public:
    int a; // 初始化列表
    A(int a_):a(a_){}
};

2、初始化方式二:构造函数初始化

?
1
2
3
4
5
6
class A
{
public:
    int a; // 初始化列表
    A(int a_, bool b) { a = a_; }
};

3、初始化方式三:声明时初始化(也称就地初始化,c++11后支持)

?
1
2
3
4
5
6
class A
{
public:
    int a = 1; // 声明时初始化
    A() {}
};

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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中,标准还允许使用等号= 或者 花括号{} 进行就地的非静态成员变量初始化。

?
1
2
3
4
struct init {
    int a = 1;
    double b {1.2};
};

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

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

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

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

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

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

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#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,别人在看你代码的时候,点一下调到声明也能看到你赋予的初始值,不用再去看构造函数那里给的什么值
第二个优点更有用了,比如你要定义多个构造函数,每个构造函数都用列表初始化的方法初始化,多麻烦呀,请看下面的例子,妈妈看了再也不用担心我想用其他初始化方法了

?
1
2
3
4
5
6
7
8
9
10
11
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、构造函数初始化的使用场景

第一个就是拷贝和赋值构造函数里(不然怎么叫赋值构造函数呢)
第二个就是比较无聊的情况了,比如你想把几个成员函数都初始化成一个值,请看下面例子

?
1
2
3
4
5
6
7
8
class Group {
public:
    Group() {data1 = data2 = data3 = 0;}
private:
    int data1;
    int data2;
    int data3;
};

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

到此这篇关于C++类成员初始化的三种方式的文章就介绍到这了,更多相关C++类成员初始化的方式内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://bbs.huaweicloud.com/blogs/281096

延伸 · 阅读

精彩推荐
  • C/C++C语言实现电脑关机程序

    C语言实现电脑关机程序

    这篇文章主要为大家详细介绍了C语言实现电脑关机程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    xiaocaidayong8482021-08-20
  • C/C++详解c语言中的 strcpy和strncpy字符串函数使用

    详解c语言中的 strcpy和strncpy字符串函数使用

    strcpy 和strcnpy函数是字符串复制函数。接下来通过本文给大家介绍c语言中的strcpy和strncpy字符串函数使用,感兴趣的朋友跟随小编要求看看吧...

    spring-go5642021-07-02
  • C/C++C/C++经典实例之模拟计算器示例代码

    C/C++经典实例之模拟计算器示例代码

    最近在看到的一个需求,本以为比较简单,但花了不少时间,所以下面这篇文章主要给大家介绍了关于C/C++经典实例之模拟计算器的相关资料,文中通过示...

    jia150610152021-06-07
  • C/C++深入理解goto语句的替代实现方式分析

    深入理解goto语句的替代实现方式分析

    本篇文章是对goto语句的替代实现方式进行了详细的分析介绍,需要的朋友参考下...

    C语言教程网7342020-12-03
  • C/C++C++之重载 重定义与重写用法详解

    C++之重载 重定义与重写用法详解

    这篇文章主要介绍了C++之重载 重定义与重写用法详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...

    青山的青6062022-01-04
  • C/C++C语言中炫酷的文件操作实例详解

    C语言中炫酷的文件操作实例详解

    内存中的数据都是暂时的,当程序结束时,它们都将丢失,为了永久性的保存大量的数据,C语言提供了对文件的操作,这篇文章主要给大家介绍了关于C语言中文件...

    针眼_6702022-01-24
  • C/C++学习C++编程的必备软件

    学习C++编程的必备软件

    本文给大家分享的是作者在学习使用C++进行编程的时候所用到的一些常用的软件,这里推荐给大家...

    谢恩铭10102021-05-08
  • C/C++c++ 单线程实现同时监听多个端口

    c++ 单线程实现同时监听多个端口

    这篇文章主要介绍了c++ 单线程实现同时监听多个端口的方法,帮助大家更好的理解和学习使用c++,感兴趣的朋友可以了解下...

    源之缘11542021-10-27