c++中类的对象初始化总结

目录

一、构造函数:初始化的核心

二、对象初始化的具体方式

1. 默认初始化(无参构造函数)

2. 带参数的构造函数初始化

3. 成员初始化列表(推荐)

4. 拷贝构造函数初始化

5. 列表初始化(C++11 及以上)

6. 委托构造函数(C++11 及以上)

7. 聚合类的初始化

8. 动态对象初始化(new关键字)

三、初始化与赋值的区别

总结


在 C++ 中,类的对象初始化是创建对象时为其成员变量赋予初始值的过程,核心依赖构造函数(类的特殊成员函数)。根据场景和需求,对象初始化有多种方式,下面详细介绍:

一、构造函数:初始化的核心

构造函数是与类同名的特殊成员函数,用于对象创建时的初始化,其特点:

  • 无返回值(无需写void);
  • 可重载(定义多个参数不同的构造函数);
  • 若未手动定义,编译器会生成默认构造函数(无参,仅为成员变量执行默认初始化)。

二、对象初始化的具体方式

1. 默认初始化(无参构造函数)

当类有默认构造函数(无参构造函数)时,可直接创建对象,无需传递参数。

默认构造函数的来源:

  • 手动定义:类名()
  • 编译器自动生成(仅当未定义任何构造函数时)。

示例

#include <iostream>
using namespace std;

class Person {
private:
    string name;
    int age;
public:
    // 手动定义默认构造函数
    Person() {
        name = "Unknown";
        age = 0;
        cout << "默认构造函数被调用" << endl;
    }

    void show() {
        cout << "Name: " << name << ", Age: " << age << endl;
    }
};

int main() {
    // 默认初始化(调用默认构造函数)
    Person p1;  // 正确:无参构造
    p1.show();  // 输出:Name: Unknown, Age: 0

    return 0;
}

注意:若手动定义了带参构造函数,编译器不再生成默认构造函数,此时需显式定义,否则Person p1;会报错。

2. 带参数的构造函数初始化

通过自定义带参数的构造函数,在创建对象时传递参数,直接初始化成员变量。

示例

class Person {
private:
    string name;
    int age;
public:
    // 带参数的构造函数
    Person(string n, int a) {
        name = n;  // 为成员变量赋值
        age = a;
        cout << "带参构造函数被调用" << endl;
    }

    void show() {
        cout << "Name: " << name << ", Age: " << age << endl;
    }
};

int main() {
    // 用带参构造函数初始化
    Person p2("Alice", 18);  // 直接传递参数
    p2.show();  // 输出:Name: Alice, Age: 18

    return 0;
}
3. 成员初始化列表(推荐)

构造函数的成员初始化列表用于在进入构造函数体之前,直接初始化成员变量(而非在函数体内赋值)。

适用场景

  • 初始化const成员变量(必须在定义时初始化);
  • 初始化引用成员(&,必须在定义时初始化);
  • 初始化没有默认构造函数的成员对象(如类的成员是另一个类的对象,且该类无默认构造)。

语法

类名(参数列表) : 成员1(值1), 成员2(值2), ... {
    // 构造函数体(可空)
}

示例

class Person {
private:
    string name;
    const int age;  // const成员,必须初始化
    int& id;        // 引用成员,必须初始化

public:
    // 成员初始化列表:直接初始化成员
    Person(string n, int a, int& i) : name(n), age(a), id(i) {
        // 构造函数体可做其他操作,无需再给成员赋值
        cout << "成员初始化列表被使用" << endl;
    }

    void show() {
        cout << "Name: " << name << ", Age: " << age << ", ID: " << id << endl;
    }
};

int main() {
    int num = 1001;
    Person p3("Bob", 20, num);  // 传递参数到初始化列表
    p3.show();  // 输出:Name: Bob, Age: 20, ID: 1001

    return 0;
}

优势:比在构造函数体内赋值更高效(直接初始化,而非先默认构造再赋值)。

4. 拷贝构造函数初始化

已存在的对象初始化新对象时,会调用拷贝构造函数

拷贝构造函数的语法(参数必须是同类对象的const引用):

类名(const 类名& 已有对象) {
    // 用已有对象的成员初始化当前对象的成员
}

调用场景

  • 用对象 A 初始化对象 B(类名 B = A; 或 类名 B(A););
  • 对象作为函数参数按值传递;
  • 函数返回对象(按值返回)。

示例

class Person {
private:
    string name;
    int age;
public:
    // 带参构造函数
    Person(string n, int a) : name(n), age(a) {}

    // 拷贝构造函数(自定义)
    Person(const Person& other) {
        name = other.name;  // 拷贝other的name
        age = other.age;    // 拷贝other的age
        cout << "拷贝构造函数被调用" << endl;
    }

    void show() {
        cout << "Name: " << name << ", Age: " << age << endl;
    }
};

int main() {
    Person p4("Charlie", 22);  // 先创建p4
    Person p5 = p4;            // 用p4初始化p5(调用拷贝构造)
    Person p6(p4);             // 另一种写法(同样调用拷贝构造)

    p5.show();  // 输出:Name: Charlie, Age: 22
    p6.show();  // 输出:Name: Charlie, Age: 22

    return 0;
}

注意:若未手动定义拷贝构造函数,编译器会生成默认拷贝构造函数(浅拷贝)。若类中包含指针成员,浅拷贝可能导致内存问题(需手动实现深拷贝)。

5. 列表初始化(C++11 及以上)

使用大括号{} 初始化对象,支持多种场景,且更安全(防止窄化转换,如int不能隐式接收double的小数部分)。

示例

class Person {
private:
    string name;
    int age;
public:
    // 带参构造函数(支持列表初始化)
    Person(string n, int a) : name(n), age(a) {}
    void show() { cout << name << ", " << age << endl; }
};

int main() {
    // 列表初始化(调用带参构造)
    Person p7{"David", 25};  // 等价于 Person p7("David", 25);
    Person p8 = {"Eve", 26}; // 也支持等号+大括号

    p7.show();  // David, 25
    p8.show();  // Eve, 26

    return 0;
}

优势

  • 统一初始化语法(可用于内置类型、数组、容器等);
  • 防止窄化转换(如Person p{123.45, "abc"}会编译报错,因参数类型不匹配)。
6. 委托构造函数(C++11 及以上)

允许一个构造函数调用同一个类的另一个构造函数,减少代码重复。

示例

class Person {
private:
    string name;
    int age;
public:
    // 核心构造函数(带参数)
    Person(string n, int a) : name(n), age(a) {
        cout << "核心构造函数被调用" << endl;
    }

    // 委托构造:调用带参构造函数(默认name为"Unknown",age为0)
    Person() : Person("Unknown", 0) {
        cout << "委托构造函数(无参)被调用" << endl;
    }

    // 委托构造:调用带参构造函数(仅指定age,name默认"Guest")
    Person(int a) : Person("Guest", a) {
        cout << "委托构造函数(仅age)被调用" << endl;
    }
};

int main() {
    Person p9;      // 调用无参委托构造 → 核心构造
    Person p10(30); // 调用单参委托构造 → 核心构造
    return 0;
}

输出

核心构造函数被调用
委托构造函数(无参)被调用
核心构造函数被调用
委托构造函数(仅age)被调用
7. 聚合类的初始化

聚合类是一种特殊的类(或结构体),满足:

  • 无用户定义的构造函数;
  • 无私有 / 保护的非静态成员;
  • 无基类;
  • 无虚函数。

聚合类可直接用初始化列表初始化成员(按成员声明顺序)。

示例

// 聚合类(结构体,满足聚合类条件)
struct Student {
    string name;  // 公有成员
    int age;
    float score;
};

int main() {
    // 直接初始化聚合类的成员(按声明顺序)
    Student s1 = {"Frank", 19, 90.5};
    Student s2{"Grace", 20, 88.0};  // C++11列表初始化

    cout << s1.name << ", " << s1.age << ", " << s1.score << endl;  // Frank, 19, 90.5
    return 0;
}
8. 动态对象初始化(new关键字)

new创建堆上的对象时,需显式调用构造函数初始化,后续用delete释放。

示例

class Person {
private:
    string name;
public:
    Person(string n) : name(n) {}
    void show() { cout << name << endl; }
};

int main() {
    // 动态初始化(堆上创建对象)
    Person* p11 = new Person("Helen");  // 调用带参构造
    Person* p12 = new Person{"Ivy"};    // C++11列表初始化
    Person* p13 = new Person();         // 调用默认构造(若存在)

    p11->show();  // Helen
    p12->show();  // Ivy

    // 释放堆内存
    delete p11;
    delete p12;
    delete p13;

    return 0;
}

三、初始化与赋值的区别

  • 初始化:对象创建时赋予初始值(调用构造函数或初始化列表),仅执行一次;
  • 赋值:对象创建后,通过赋值运算符(=)修改成员变量,可执行多次。

const成员、引用成员等,只能初始化,不能赋值。

总结

C++ 对象初始化方式多样,核心是通过构造函数实现,根据场景选择:

  • 简单初始化:用默认构造或带参构造;
  • 高效 / 特殊成员(const、引用):用成员初始化列表;
  • 复用对象:用拷贝构造;
  • 简洁安全:用列表初始化({});
  • 减少代码重复:用委托构造。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

start_up_go

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值