【C/C++】C++类的六个特殊成员函数,附亲测实例

26 篇文章 1 订阅
15 篇文章 0 订阅

在C++中,类的特殊成员函数是指那些由编译器自动生成的函数,它们在特定情况下会被调用,以支持类的某些操作。这些特殊成员函数包括:

  1. 默认构造函数(Default Constructor)

    • 当没有提供任何构造函数时,编译器会自动生成一个默认构造函数。
    • 它不接受任何参数,或者所有参数都有默认值。
    • 如果类中定义了其他构造函数,编译器不会自动生成默认构造函数。
  2. 复制构造函数(Copy Constructor)

    • 当一个对象作为另一个对象的副本时,编译器会调用复制构造函数。
    • 它接受一个同类型的对象的引用作为参数。
    • 如果类中定义了复制构造函数,编译器不会自动生成默认的复制构造函数。
  3. 赋值运算符(Assignment Operator)

    • 当使用赋值操作符(=)将一个对象赋值给另一个对象时,编译器会调用赋值运算符。
    • 它接受一个同类型的对象的引用作为参数。
    • 如果类中定义了赋值运算符,编译器不会自动生成默认的赋值运算符。
  4. 移动构造函数(Move Constructor)

    • 当一个对象通过移动语义(使用右值引用)被创建时,编译器会调用移动构造函数。
    • 它接受一个右值引用作为参数。
    • 如果类中定义了移动构造函数,编译器不会自动生成默认的移动构造函数。
  5. 移动赋值运算符(Move Assignment Operator)

    • 当一个对象通过移动语义被赋值时,编译器会调用移动赋值运算符。
    • 它接受一个右值引用作为参数。
    • 如果类中定义了移动赋值运算符,编译器不会自动生成默认的移动赋值运算符。
  6. 析构函数(Destructor)

    • 当对象生命周期结束时,编译器会调用析构函数。
    • 它没有参数,也不返回任何值。
    • 如果类中定义了析构函数,编译器不会自动生成默认的析构函数。

这些特殊成员函数对于类的正确使用至关重要,因为它们确保了类的资源管理(如内存分配和释放)能够正确执行。在设计类时,应该根据类的需要来决定是否需要自定义这些特殊成员函数。如果类中包含动态分配的资源(如指针、文件句柄等),通常需要自定义析构函数来释放这些资源,以避免内存泄漏。同样,如果类需要支持复制或移动操作,也应该提供相应的特殊成员函数。

#include <iostream>

class MyClass {
public:
    // 默认构造函数
    MyClass() {
        std::cout << "Default constructor called." << std::endl;
    }

    // 复制构造函数
    MyClass(const MyClass& other) {
        std::cout << "Copy constructor called." << std::endl;
        // 深拷贝或浅拷贝逻辑
        if (other.m_ptr) {
			auto n = std::strlen(other.m_ptr) + 1;
			m_ptr = new char[n];
			std::memcpy(m_ptr, other.m_ptr, n);
		}
    }

    // 赋值运算符
    MyClass& operator=(const MyClass& other) {
        std::cout << "Co				py assignment operator called." << std::endl;
        // 赋值逻辑
        if (this != &other)
        	delete[] m_ptr; // 释放已经存在的资源
        
        if(other.m_ptr != nullptr{
			auto n = std::strlen(other.m_ptr) + 1;
			m_ptr = new char[n];
			std::memcpy(m_ptr, other.m_ptr, n);
		}
        return *this;	
    }

    // 移动构造函数 -- 新建对象,不需要const
    MyClass(MyClass&& other) noexcept {
        std::cout << "Move constructor called." << std::endl;
        // 移动逻辑
        if (other.m_ptr) 
        	m_ptr = std::move(other.m_ptr)
       	
       	other.m_ptr = nullptr;
    }

    // 移动赋值运算符 -- 对已有的对象进行赋值,不需要const
    MyClass& operator=(MyClass&& other) noexcept {
        std::cout << "Move assignment operator called." << std::endl;
        // 移动赋值逻辑
        if (this != &other) {
			delete[] m_ptr; //释放已存在的资源
		}
		if (other.mtr)
			m_ptr = std::move(other.m_ptr);
		
		other.m_ptr = nullptr;
		
        return *this;
    }

    // 析构函数
    ~MyClass() {
        std::cout << "Destructor called." << std::endl;
        if (m_ptr)
        	delete[] m_ptr;
    }
private:
	char *m_ptr;
};

int main() {
    // 使用默认构造函数创建对象
    MyClass obj1;

    // 使用复制构造函数创建对象
    MyClass obj2(obj1);

    // 使用赋值运算符
    MyClass obj3;
    obj3 = obj2;

    // 使用移动构造函数创建对象
    MyClass obj4(std::move(obj1));

    // 使用移动赋值运算符
    MyClass obj5;
    obj5 = std::move(obj4);

    return 0;
}
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值