C++ - 构造函数(移动改造函数-右值引用)

C++ 中的构造函数类型

  1. 默认构造函数:
    • 没有参数,用于创建默认初始化的对象。
    • 如果没有显式定义,编译器会自动生成一个默认构造函数。
    class MyClass {
    public:
        MyClass() {} // 默认构造函数
    };
    
  2. 参数化构造函数:
    • 接受一个或多个参数,用于创建以特定值初始化的对象。
    class MyClass {
    public:
        MyClass(int value) : _value(value) {} // 参数化构造函数
    private:
        int _value;
    };
    
  3. 拷贝构造函数:
    • 接受一个同类型的对象作为参数,用于创建该对象的副本。
    class MyClass {
    public:
        MyClass(const MyClass& other) : _value(other._value) {} // 拷贝构造函数
    private:
        int _value;
    };
    
  4. 移动构造函数:
    • 接受一个右值引用作为参数,用于将资源从一个对象转移到另一个对象。
    class MyClass {
    public:
        MyClass(MyClass&& other) : _value(std::move(other._value)) {} // 移动构造函数
    private:
        int _value;
    };
    
  5. 转换构造函数:
    • 接受一个不同类型的值作为参数,用于将该值转换为当前类型。
    class MyClass {
    public:
        MyClass(int value) : _value(value) {} // 转换构造函数
    private:
        int _value;
    };
    

右值引用构造函数的好处:

  1. 避免不必要的拷贝: 对于临时对象或即将被销毁的对象,使用右值引用构造函数可以避免不必要的拷贝操作,提高效率。

  2. 资源转移: 右值引用构造函数允许将资源从一个对象转移到另一个对象,而不是进行拷贝,这对于管理动态分配的内存和其他资源非常有用。

举例说明:

#include <iostream>
#include <string>

class MyClass {
public:
    MyClass(const std::string& str) : _str(str) {
        std::cout << "拷贝构造函数被调用\n";
    }

    MyClass(std::string&& str) : _str(std::move(str)) {
        std::cout << "移动构造函数被调用\n";
    }

    std::string getStr() const {
        return _str;
    }

private:
    std::string _str;
};

int main() {
    // 使用拷贝构造函数
    MyClass obj1("Hello");
    MyClass obj2(obj1); 
    std::cout << "obj2.getStr(): " << obj2.getStr() << std::endl;

    // 使用移动构造函数
    MyClass obj3(std::move(obj1)); 
    std::cout << "obj3.getStr(): " << obj3.getStr() << std::endl;
    std::cout << "obj1.getStr(): " << obj1.getStr() << std::endl; // obj1 的 _str 被移动到 obj3,这里应该为空

    return 0;
}

输出:

拷贝构造函数被调用
obj2.getStr(): Hello
移动构造函数被调用
obj3.getStr(): Hello
obj1.getStr(): 

在这个例子中,obj2 使用拷贝构造函数创建了 obj1 的副本,而 obj3 使用移动构造函数将 obj1 的资源转移到了自己。由于移动构造函数将资源转移,obj1 的 _str 属性被清空。

构造函数的主要修饰语法

1. 访问修饰符:
  • public: 公共构造函数,可以在任何地方被访问。
  • private: 私有构造函数,只能在类内部或友元函数中被访问,限制了对象的创建。
  • protected: 受保护的构造函数,只能在类内部、子类和友元函数中被访问。
class MyClass {
public:
    MyClass() {} // 公共构造函数
private:
    MyClass(int value) {} // 私有构造函数
protected:
    MyClass(const MyClass& other) {} // 受保护的构造函数
};
2. 关键字 explicit:
  • 用于阻止构造函数进行隐式转换。
class MyClass {
public:
    explicit MyClass(int value) {} // 阻止将int隐式转换为MyClass
};

int main() {
    MyClass obj1(10); // 正确,显式调用构造函数
    MyClass obj2 = 10; // 错误,无法隐式转换
    return 0;
}
3. constexpr 修饰符:
  • 用于创建常量表达式构造函数,它必须在编译时计算出结果。
class MyClass {
public:
    constexpr MyClass(int value) : _value(value) {} // 常量表达式构造函数
private:
    int _value;
};

int main() {
    constexpr MyClass obj(10); // 在编译时初始化
    return 0;
}
4. delete 修饰符:
  • 用于禁用默认构造函数。
class MyClass {
public:
    MyClass(int value) {} 
private:
    MyClass() = delete; // 禁用默认构造函数
};
5. = default:
  • 用于显式地调用默认构造函数。
class MyClass {
public:
    MyClass() = default; // 显式地调用默认构造函数
};
6. = delete:
  • 用于显式地禁止默认构造函数。
class MyClass {
public:
    MyClass() = delete; // 禁止默认构造函数
};

注意:

  • 访问修饰符决定了构造函数的访问权限。
  • explicit 阻止隐式类型转换,但不会阻止显式转换。
  • constexpr 用于创建常量表达式构造函数,它必须在编译时计算出结果。
  • delete 禁用默认构造函数,阻止编译器自动生成默认构造函数。
  • = default 和 = delete 用于显式地指定默认构造函数的行为。

希望这些信息能帮助你理解构造函数修饰语法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值