ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C++ 类的非静态数据成员默认初始化

2022-09-11 22:31:29  阅读:367  来源: 互联网

标签:静态数据 初始化 PrintX C++ init 11 world


目录

C++11 之前使用默认初始化

C++11 之前对非静态数据成员初始化需要用到初始化列表。

有个问题是,如果类的数据成员比较多,我们又需要定制一些数据成员的初始化操作的时候,需要写很多的构造函数。

来看一个例子:

#include <iostream>
#include <string>

class X {
public:
    X() : a_(0), b_(0.), c_("hello world") {}
    X(int a) : a_(a), b_(0.), c_("hello world") {}
    X(double b) : a_(0), b_(b), c_("hello world") {}
    X(const std::string c) : a_(0), b_(0.), c_(c) {}
    
    void PrintX() {
        std::cout << "----------------------" << std::endl;
        std::cout << "a_: " << this->a_ << std::endl;
        std::cout << "b_: " << this->b_ << std::endl;
        std::cout << "c_: " << this->c_ << std::endl;
    }

private:
    int a_;
    double b_;
    std::string c_;
};

int main() {
    X* x_1 = new X();
    x_1->PrintX();

    X* x_2 = new X(1);
    x_2->PrintX();

    X* x_3 = new X(2.0);
    x_3->PrintX();

    X* x_4 = new X("C++");
    x_4->PrintX();
}

因为有时候要给不同的成员变量进行初始化,所以要写好几个不同版本的构造函数,并且可以发现构造函数里有很多冗余代码。

运行结果:

linrongjian@hhb-ssd:/data/modern_cpp$ g++ -std=c++11 nonstatic_datamemeber_init.cpp -o nonstatic_datamemeber_init
linrongjian@hhb-ssd:/data/modern_cpp$ ./nonstatic_datamemeber_init
----------------------
a_: 0
b_: 0
c_: hello world
----------------------
a_: 1
b_: 0
c_: hello world
----------------------
a_: 0
b_: 2
c_: hello world
----------------------
a_: 0
b_: 0
c_: C++

这种方式在数据成员变多的时候,需要频繁地更改和增加构造函数,维护起来非常的麻烦。

C++11 的默认初始化方式

C++11 允许在声明非静态数据成员的时候同时用 =(声明时默认初始化) 和 {} (列表初始化)。

还是刚才的例子,可以这样写:

#include <iostream>
#include <string>

class X {
public:
    X() {}
    X(int a) : a_(a) {}
    X(double b) : b_(b) {}
    X(const std::string c) : c_(c) {}
    
    void PrintX() {
        std::cout << "----------------------" << std::endl;
        std::cout << "a_: " << this->a_ << std::endl;
        std::cout << "b_: " << this->b_ << std::endl;
        std::cout << "c_: " << this->c_ << std::endl;
    }

private:
    // 这里也可以用列表初始化 {}
    int a_ = 0;
    double b_ = 0.;
    std::string c_ = "hello world";
};

int main() {
    X* x_1 = new X();
    x_1->PrintX();

    X* x_2 = new X(1);
    x_2->PrintX();

    X* x_3 = new X(2.0);
    x_3->PrintX();

    X* x_4 = new X("C++");
    x_4->PrintX();
}

可以发现在声明数据成员的时候直接用 = 初始化(也可以 {} 列表初始化)和构造函数的列表初始化同时使用了。

同时构造函数少了很多冗余代码,每个构造函数只需要专注于特殊成员的初始化(而不是写出全部数据成员的初始化),对于没写出来的数据成员,默认使用声明时初始化的值。

显然这种方式增强了代码可维护性。

运行效果和上面是等效的:

linrongjian@hhb-ssd:/data/modern_cpp$ g++ -std=c++11 nonstatic_datamemeber_init.cpp -o nonstatic_datamemeber_init
linrongjian@hhb-ssd:/data/modern_cpp$ ./nonstatic_datamemeber_init
----------------------
a_: 0
b_: 0
c_: hello world
----------------------
a_: 1
b_: 0
c_: hello world
----------------------
a_: 0
b_: 2
c_: hello world
----------------------
a_: 0
b_: 0
c_: C++

位域默认初始化(C++20)

有些变量在存储时不需要一个完整的字节,而只需要占用几个位。

为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几 个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。

C++20 允许对数据成员的位域进行默认初始化。

例:

#include <iostream>

class S {
public:
    int x : 8 = 11;
    int y : 4{7};
};

int main() {
    S* s = new S();
    std::cout << s->x << ' ' << s->y << std::endl;
}

这里低 8 位被初始化为 11,高 4 位被初始化为 7

linrongjian@hhb-ssd:/data/modern_cpp$ g++ -std=c++2a bitfield_init.cpp -o bitfield_init
linrongjian@hhb-ssd:/data/modern_cpp$ ./bitfield_init
11 7

参考资料

  1. 现代C++语言核心特性解析

标签:静态数据,初始化,PrintX,C++,init,11,world
来源: https://www.cnblogs.com/linrj/p/16685003.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有