目录

如果类中有动态分配的对象,就必须显式地定义构造函数和赋值操作符,以确保对象被正确复制

编译器一般会给四种方法生成默认版本:

默认构造函数、析构函数、复制构造函数、赋值操作符

复制构造函数会根据已有对象创建一个新对象,默认生成的复制构造函数,会根据已有对象成员变量进行浅copy。

下面是调用到复制构造函数的地方:

  • 对象以传值方式传递给方法或返回
  • 对象使用下述语法初始化:Myclass a = b;
  • 对象位于在花括号中的初始化列表内
  • 对象在异常中被抛出或捕获

赋值操作符用来将一个对象的值赋给另一个对象:a = b,它与复制构造函数的区别在于,被赋值的对象已经存在了。

实现赋值操作符有一些指导原则:

  • 为右侧操作数使用const引用
  • 以引用方式返回*this,以支持操作符链
  • 在设置新状态前销毁已存在的状态
  • 通过比较this和&rth检测自赋值(a=a)

如果你想创建不能被客户复制的对象(只能是引用对象),则应该将复制构造函数和赋值操作符声明为类的私有成员,或者使用boost::nocopyable

如果类分配了资源,一般来说,析构函数和复制构造函数、赋值操作符是要一起使用的。

(声明用于子类化的空虚析构函数是特例,因为它没有执行实际的内存释放操作),这样的概念被表述为"类的正统规范形式"

像下面的代码就会编译报错,因为x和y的析构函数都试图释放相同的内存。

class Array{
public:
    explicit Array(int size): mSize(size), mData(new int[size])
    {
    }
    ~Array() {
        delete[] mData;
    };
    int Get(int index) const;
    void Set(int index, int value);
    int GetSize() const;
private:
    int mSize;
    int* mData;
};
int main() {
    {
        Array x(100);
        Array y = x;
    }
    std::cout << "end" << std::endl;
    return 0;
}

明确告诉编译器生成一个私有默认构造函数和一个虚析构函数,且两个函数均使用编译器生成的版本。

class MyClass
{
public:
    virtual ~MyClass() = default;

private:
    MyClass() = default;
};

class NonCopyable
{
public:
    NonCopyable() = default;
    NonCopyable(const NonCopyable&) = delete;
    NonCopyable & operator=(const NonCopyable&) = delete;

};

这样禁止生成复制构造函数和赋值操作符,也可以使得某个类不可复制。

定义构造函数和赋值操作符

cpp文件

h文件

//
// Created by hanhandi on 2023/3/12.
//

#ifndef UNTITLED_MYARRAY_H
#define UNTITLED_MYARRAY_H

#include <string>

class Array{
public:
    // 默认构造函数
    Array();
    // 非默认构造函数
    explicit Array(int size);
    // 析构函数
    ~Array();
    // 复制构造函数
    Array(const Array& i_array);
    // 赋值操作符
    Array& operator=(const Array& i_array);

    std::string Get(int index) const;
    bool Set(int index, const std::string& str);
    int GetSize() const;

private:
    int mSize;
    std::string* mArray;
};



#endif //UNTITLED_MYARRAY_H

#include <iostream>
#include "MyArray.h"

int main() {
    Array a; // 默认构造函数
    Array b(10); // 非默认构造函数
    Array c(b); // 复制构造函数
    Array d = a; // 复制构造函数
    b = c; // 赋值操作符
    std::cout << "end" << std::endl;
    return 0;
}