C++基础,关于书中所说的“避免‘双重初始化’”,请问能帮忙解释一下下面几句话是什么意思呢?

书中原话:“**请通过成员初始化器显式地初始化成员对象,这样,可以避免‘双重初始化’成员对象的开销,一次是当成员对象的默认构造函数被调用时,另一次就是在构造函数体中(或者后来)调用设置函数被初始化成员对象时**。”

这句话我无法理解 它是怎样“避免‘双重初始化’”的。

类类型的数据成员对象在进入函数体前已经构造完成,也就是说在成员初始化列表处进行构造对象的工作,调用构造函数,在进入函数体之后,进行的是对已经构造好的类对象的赋值,又调用个拷贝赋值操作符才能完成
比如说

#include <iostream>

using namespace std;

class A
{
public:
    A() { cout << "A::A" << endl; }
    A(A& a) { cout << "A::A" << endl; }
};

class B
{
private:
    A a;
public:
    B():a() { }
};

int main() {
    B b;
    return 0;
}

A::A

#include <iostream>

using namespace std;

class A
{
public:
    A() { cout << "A::A" << endl; }
    A(A& a) { cout << "A::A" << endl; }
};

class B
{
private:
    A a;
public:
    B() { a = A(); }
};

int main() {
    B b;
    return 0;
}

A::A
A::A

后一个版本就是双重初始化。

看一下这段代码,使用两种类初始化方式来初始化成员类变量,第一次使用不含参构造,不调用成员变量初始化;第二次使用含参构造,对应调用成员变量初始化。
输出的结果是下图,不调用成员初始化的构造函数时,成员函数调用了两次设置变量的函数,而这两句在程序中都是初始化的作用,即双重初始化。

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

class component{
    private:
        int a, b;
        void _set(int _a, int _b){
            cout << "Set a = " << _a << ", b = " << _b << endl;
            a = _a; b = _b;
        }
    public:
        component(){                   _set(0, 0); }
        component(int a, int b){       _set(a, b); }
        void setValue(int a, int b){   _set(a, b); }
};

class test{
    private:
        component com;
    public:
        test(){ com.setValue(5,4); }
        test(int a, int b):com(a, b){ }
};

int main(){
    cout << "双重初始化" << endl; 
    test t1;

    cout << "单次初始化" << endl;
    test t2(5, 4);

    return 0;
}

运行结果是这样的
图片说明