c++ 构造函数详细介绍

c++对象的创建

c++对象的创建一般分为以下三个阶段:

  1. 分配内存:
    ■ 在堆区、栈区或者全局数据区留出足够多的字节。这个时候的内存还比较“原始”,没有被“教化”,它所包含的数据一般是零值或者随机值,没有实际的意义;
    ■ 这通常是通过使用 new 运算符动态分配内存或者在栈上为对象分配内存空间。
  2. 初始化:
    ■ 初始化就是首次对内存赋值,让它的数据有意义。注意是首次赋值,再次赋值不叫初始化。初始化的时候还可以为对象分配其他的资源(如动态分配内存等),或者提前进行一些计算等。初始化就是调用构造函数。
    ■ 在构造函数中,可以使用成员初始化列表(Member Initialization List)或构造函数体内的赋值语句来初始化成员变量。这些初始化操作将对象的成员变量设置为适当的值。
  3. 返回对象地址:
    在构造函数执行完毕后,对象的地址将被返回给对象的引用或指针,使得可以通过该引用或指针访问和操作对象。

c++ 构造函数

C++ 构造函数(Constructor)是一种特殊的成员函数,用于创建和初始化类的对象。构造函数在对象创建时自动调用,并负责为对象的成员变量赋予初始值。

构造函数的分类:

构造函数类别解释
默认构造函数(Default Constructor)创建类的时候没有写构造函数,则系统会自动生成默认的无参构造函数,函数为空,什么都不做;
参数化构造函数(Parameterized Constructor)带有参数的构造函数,用于根据提供的参数值进行对象的初始化。参数化构造函数允许在创建对象时传递不同的参数,以便根据参数值初始化对象的成员变量。也可以理解伟重载构造函数
拷贝构造函数(Copy Constructor)接受同类型对象作为参数的构造函数,用于创建新对象并将传递的对象的值复制到新对象中。拷贝构造函数常用于对象的复制和创建对象副本。 若没有显示的写复制构造函数,则系统会默认创建一个复制构造函数,但当类中有指针成员时,由系统默认创建该复制构造函数会存在风险。
移动构造函数(Move Constructor)接受同类型对象的右值引用作为参数的构造函数,用于创建新对象并从传递的对象中“移动”资源(如动态分配的内存)到新对象中。移动构造函数常用于提高性能和资源管理。
类型转换构造函数(Conversion Constructor)一种特殊的构造函数,用于将一种类型的对象转换为另一种类型的对象。它允许在需要时隐式地进行类型转换,或者通过显式构造函数调用进行显式类型转换。

默认构造函数:

C++ 默认拷贝构造函数(Default Copy Constructor)是编译器自动生成的构造函数,用于执行对象的浅拷贝(shallow copy)。如果在类中没有显式定义拷贝构造函数,编译器会自动生成默认的拷贝构造函数。

默认拷贝构造函数的特点如下:

  • 接受同类型对象的常量引用作为参数。
  • 执行逐个成员变量的复制操作,将传递的对象的值复制到新对象中的对应成员变量。
  • 对于指针成员变量,执行浅层复制,即复制指针的值而不是复制指针指向的数据。
class MyClass {
public:
    int data;
    int* ptr;

    // 默认构造函数
    MyClass() {
        data = 0;
        ptr = new int(0);
    }

    // ...
};

上述示例中,如果没有显式定义拷贝构造函数,编译器会自动生成一个默认的拷贝构造函数。该默认拷贝构造函数将执行浅层复制,即复制 data 的值和 ptr 的指针值。

使用默认拷贝构造函数可以进行对象的浅拷贝,即复制对象的成员变量的值。但对于指针类型的成员变量,浅拷贝可能会导致多个对象共享同一块内存,从而引发潜在的问题。如果需要执行深层复制或资源管理,通常需要显式定义自定义的拷贝构造函数。

参数化构造函数:

C++ 参数化构造函数(Parameterized Constructor)是一种构造函数,接受参数用于在对象创建时进行自定义的初始化操作。通过参数化构造函数,可以根据提供的参数值来初始化对象的成员变量。

参数化构造函数的特点如下:

  • 接受一个或多个参数,用于传递初始化所需的值。
  • 参数个数、类型和顺序要与构造函数的声明相匹配。
  • 可以根据需求定义多个不同的参数化构造函数,以提供不同的初始化方式。
class MyClass {
public:
    int data;

    // 默认构造函数
    MyClass() {
        data = 0;
    }

    // 参数化构造函数
    MyClass(int value) {
        data = value;
    }
};

通过参数化构造函数,我们可以在创建对象时传递不同的参数值,以便根据参数值初始化对象的成员变量。例如:

MyClass obj1;          // 调用默认构造函数创建对象 obj1,data = 0
MyClass obj2(42);      // 调用参数化构造函数创建对象 obj2,data = 42

拷贝构造函数:

C++ 拷贝构造函数(Copy Constructor)是一种特殊的构造函数,用于创建新对象并将另一个同类型对象的值复制到新对象中。拷贝构造函数通常用于对象的复制和创建对象副本。

拷贝构造函数的特点如下:

  • 接受同类型对象的常量引用作为参数;它只有一个参数,即参数类型是本类的引用。
  • 用于创建新对象,并将传递的对象的值复制到新对象中。
  • 对于指针成员变量,默认情况下执行浅层复制,即复制指针的值而不是复制指针指向的数据。
class MyClass {
public:
    int data;
    int* ptr;

    // 默认构造函数
    MyClass() {
        data = 0;
        ptr = new int(0);
    }

    // 拷贝构造函数(自定义)
    MyClass(const MyClass& other) {
        data = other.data;
        ptr = new int(*(other.ptr));
    }
};

使用拷贝构造函数可以创建对象的副本,确保新对象与原始对象具有相同的值。例如:

MyClass obj1;                  // 调用默认构造函数创建对象 obj1
obj1.data = 42;
*(obj1.ptr) = 100;

MyClass obj2(obj1);            // 调用拷贝构造函数创建对象 obj2,复制 obj1 的值

默认拷贝构造函数和自定义拷贝构造函数:

  1. 默认拷贝构造函数:
    默认拷贝构造函数是由编译器自动生成的构造函数,当没有显式定义拷贝构造函数时,编译器会为类生成默认的拷贝构造函数。
    默认拷贝构造函数执行浅拷贝(shallow copy),即逐个成员变量地复制源对象的值到新对象中。
    对于指针成员变量,默认拷贝构造函数只会复制指针的值,而不会复制指针指向的数据。
class MyClass {
public:
    int data;
    int* ptr;

    // ...
};

如果没有自定义拷贝构造函数,编译器会为 MyClass 类生成一个默认的拷贝构造函数,执行浅拷贝。

  1. 自定义拷贝构造函数:
    自定义拷贝构造函数是用户根据类的需求自行定义的构造函数,用于根据自定义逻辑执行对象的复制操作。
    自定义拷贝构造函数可以根据需要接受同类型对象的引用或常量引用作为参数,以及其他必要的参数。
    自定义拷贝构造函数的实现可以执行 深拷贝(deep copy) 或其他自定义的复制逻辑。
class MyClass {
public:
    int data;
    int* ptr;

    // 自定义拷贝构造函数
    MyClass(const MyClass& other) {
        data = other.data;
        ptr = new int(*(other.ptr));
    }
};

在上述示例中,MyClass 类定义了一个自定义的拷贝构造函数。自定义拷贝构造函数根据需要接受同类型对象的常量引用作为参数,并执行深层复制,将源对象的值复制到新对象中。

移动构造函数:

C++ 移动构造函数(Move Constructor)是一种特殊的构造函数,用于将一个对象的资源所有权从一个对象转移到另一个对象,而无需执行深层复制操作。移动构造函数通常用于提高对象的性能和效率,特别是在处理大型对象或包含资源的对象时。

移动构造函数的特点如下:

  • 接受同类型对象的右值引用(&&)作为参数。
  • 用于创建新对象并从传递的右值引用对象中"窃取"资源。
  • 通常在移动语义中,移动构造函数会将传递对象的指针或资源的所有权转移到新对象,而不执行深层复制。
class MyClass {
public:
    int* data;

    // 默认构造函数
    MyClass() {
        data = new int(0);
    }

    // 移动构造函数
    MyClass(MyClass&& other) {
        data = other.data;
        other.data = nullptr;  // 将原对象的指针置为空,避免重复释放资源
    }
};

在上述示例中,MyClass 类定义了一个移动构造函数。移动构造函数接受一个同类型对象的右值引用 MyClass&& other 作为参数,并使用右值引用对象 other 中的资源来创建新对象。

在移动构造函数的实现中,将传递对象的指针 data 赋给新对象,然后将原对象的指针置为空,避免重复释放资源。

MyClass obj1;                  // 调用默认构造函数创建对象 obj1
obj1.data = new int(42);

MyClass obj2(std::move(obj1));  // 调用移动构造函数创建对象 obj2,转移 obj1 的资源所有权

在上述示例中,通过使用 std::move() 将对象 obj1 转换为右值引用,并传递给移动构造函数,创建了一个新对象 obj2。这样,obj2 将获得 obj1 的资源所有权,而 obj1 中的指针被置为空。

类型转换构造函数

类型转换构造函数(Conversion Constructor)是一种特殊的构造函数,用于将一种类型的对象转换为另一种类型的对象。它允许在需要时隐式地进行类型转换,或者通过显式构造函数调用进行显式类型转换。

类型转换构造函数具有以下特点:

  • 它是一个构造函数,没有返回类型(包括 void)。
  • 它可以带有一个或多个参数,用于定义从当前类型到目标类型的转换方式。
  • 它可以定义隐式类型转换,这意味着在需要时编译器会自动调用类型转换构造函数,将一个对象转换为另一个类型。
  • 它也可以通过显式构造函数调用进行显式类型转换。
class MyInt {
public:
    int value;

    // 类型转换构造函数
    MyInt(double val) {
        value = static_cast<int>(val);
    }
};

int main() {
    double num = 3.14;
    MyInt myNum = num;  // 隐式类型转换,调用类型转换构造函数

    MyInt myNum2 = MyInt(5.67);  // 显式类型转换,通过构造函数调用
}
  • 33
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Codec Conductor

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

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

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

打赏作者

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

抵扣说明:

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

余额充值