玩命加载中 . . .

13.1-拷贝、赋值与销毁


13.1 拷贝、赋值与销毁

13.1.1 copy constructor

拷贝构造函数

第一个参数是引用类型

Foo(const Foo&);

  • 直接初始化和拷贝初始化
Person p1("kavin", 23);     // 直接初始化,调用自定义的构造函数
Person p2(p1);              // 直接初始化,调用拷贝构造函数
Person p3 = p1;             // 拷贝初始化,调用拷贝构造函数

使用拷贝初始化时,我们要求编译器将右侧运算对象拷贝到正在创建的对象中,如果需要的话还要进行类型转换

class Person {
private:
    string name;
    int age;
public:
    Person(string name, int age) : name(name), age(age) {
        cout << "constructor" << endl;
    }
    Person(const Person& rhs) {
        cout << "copy constructor" << endl;
        name = rhs.name;
        age = rhs.age;
    }
};

int main() {
    Person p1("kavin", 23); // 调用自定义构造函数
    Person *ptr = new Person("kavin", 34);  // 调用自定义构造函数
    Person p2(p1);          // 调用拷贝构造函数直接初始化
    Person p3 = p1;         // 调用拷贝构造函数拷贝初始化
    return 0;
}
// constructor
// constructor
// copy constructor
// copy constructor

用等号来构造对象就是拷贝初始化,后面带个括号的是直接初始化

拷贝初始化不仅在我们用=定义变量时发生,在下列情况下也会发生
1、将一个对象作为实参传递给一个非引用类型的形参

void func(Person p) {
    cout << "Entering func" << endl;
    return;
}
int main() {
    Person p1("kavin", 23);
    func(p1);
    return 0;
}
// constructor
// copy constructor 调用了拷贝构造函数
// Entering func

也说明了拷贝构造函数必须是引用类型,否则,实参传递给拷贝构造函数的形参时就得再调用拷贝构造函数,就会陷入循环

2、 从一个返回类型为非引用类型的函数返回一个对象

Person func() {
    Person *p = new Person("lisa", 34);
    return *p;
}

int main() {
    Person p1 = func();
    return 0;
}
// constructor
// copy constructor 调用了拷贝构造函数

13.1.2 copy-assignment operator

拷贝赋值运算符

参数是类类型的const引用
返回值是指向其左侧运算对象的引用

Foo& operator=(const foo&);

代码示例

class Person {
private:
    string name;
    int age;
public:
    Person() {}
    Person(string name, int age) : name(name), age(age) {}
    Person& operator=(const Person& rhs) {
        name = rhs.name;
        age = rhs.age;
        return *this;
    }
};

int main() {
    Person p1("kavin", 23); // 调用自定义构造函数
    Person p2;  // 调用默认构造函数
    p2 = p1;    // 调用拷贝赋值运算符
    return 0;
}

这里是给对象赋值,不是构造对象,所以调用拷贝赋值运算符,而不是拷贝构造函数

13.3.3 destructor

析构函数
  1. 不接受参数,也没有返回值
  2. 不能被重载
  3. 对一个给定类,只会有唯一一个析构函数
  4. 当指向一个对象的引用指针离开作用域时,『不会调用析构函数』
~Foo();

在一个析构函数中,首先执行函数体,然后销毁成员,成员按初始化顺序的逆序销毁

如果一个类需要析构函数,那肯定也需要拷贝构造函数拷贝赋值运算符,尤其是含有动态分配内存的类,因为合成析构函数不会delete一个指针数据成员


文章作者: kunpeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kunpeng !
  目录