Skip to the content.

036-成员初始化列表

通常我们需要初始化一个类中的成员变量的时候,都是在构造函数内初始化的,在C++中也可以这样,例如

#include <iostream>

class Person {
private:
    std::string mName;
public:
    Person() {
        mName = "Unknown";
    }

    Person(const std::string& name) {
        mName = name;
    }

    const std::string &getName() const {
        return mName;
    }
};

int main() {
    Person p0;
    std::cout << p0.getName() << std::endl;
    Person p1("张三");
    std::cout << p1.getName() << std::endl;
    return 0;
}

F:\Projects\ClionProjects\test\cmake-build-debug-cygwin\test.exe
Unknown
张三

进程已结束,退出代码为 0

能跑,不错

我们使用成员初始化列表后

#include <iostream>

class Person {
private:
    std::string mName;
    int mAge;
public:
    Person() : mName("UnKnown"), mAge(1) {}

    Person(const std::string &name, int age) : mName(name), mAge(age) {}

    const std::string &getName() const {
        return mName;
    }

    const int &getAge() const {
        return mAge;
    }
};

int main() {
    Person p0;
    std::cout << p0.getName() << ", " << p0.getAge() << std::endl;
    Person p1("张三", 18);
    std::cout << p1.getName() << ", " << p1.getAge() << std::endl;
    return 0;
}
F:\Projects\ClionProjects\test\cmake-build-debug-cygwin\test.exe
UnKnown, 1
张三, 18

进程已结束,退出代码为 0

效果一样

注意:在使用成员初始化列表的时候,按照成员变量的定义顺序来,否则可能会有问题

那么,为什么要使用成员初始化列表呢,首先,代码好看了,还有关键的一点,如果是类对象,使用上面的方式就会初始化两次,造成内存浪费,看下面的例子

#include <iostream>

class Pet {
public:
    Pet() {
        std::cout << "Init pet without age" << std::endl;
    }

    Pet(int age) {
        std::cout << "Init pet with age " << age << std::endl;
    }
};

class Person {
private:
    std::string mName;
    Pet mPet;
public:
    Person() : mName("UnKnown") {
        mPet = Pet(8);
    }

    const std::string &getName() const {
        return mName;
    }

};

int main() {
    Person person;
    return 0;
}

看起来没啥毛病,但是运行结果为

F:\Projects\ClionProjects\test\cmake-build-debug-cygwin\test.exe
Init pet without age
Init pet with age 8

进程已结束,退出代码为 0

想不到吧,因为上面的Pet mPet其实也进行了一次初始化,使用成员初始化列表后

#include <iostream>

class Pet {
public:
    Pet() {
        std::cout << "Init pet without age" << std::endl;
    }

    Pet(int age) {
        std::cout << "Init pet with age " << age << std::endl;
    }
};

class Person {
private:
    std::string mName;
    Pet mPet;
public:
    Person() : mName("UnKnown"), mPet(Pet(8)) {
    }

    const std::string &getName() const {
        return mName;
    }

};

int main() {
    Person person;
    return 0;
}

运行结果

F:\Projects\ClionProjects\test\cmake-build-debug-cygwin\test.exe
Init pet with age 8

进程已结束,退出代码为 0

正常多了,另外, mPet(Pet(8))也可以写为mPet(8)也是没问题的


https://www.bilibili.com/video/BV1Zi4y1F7o1