C++拷贝控制

2018-10-14  本文已影响0人  m风满楼

前言

C++通过在类中定义几个成员函数来控制的对象的拷贝,移动,赋值和销毁,分别如下:

  1. 拷贝构造函数和移动构造函数定义:当用同一类型的另一个对象初始化本对象时做什么(注意区分初始化和赋值)
  2. 拷贝和移动赋值函数定义:将一个对象赋予同类型的的另一个对象的时候做什么
  3. 析构函数定义当此类型对象销毁时做什么

拷贝,赋值,销毁。

1. 拷贝构造

C++拷贝构造函数是一种特殊的构造函数,用于同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数的名称必须和类名称一致,它的第一个参数必须是一个本类型对象的引用(原因是如果不是引用,则函数实参的初始化需要执行拷贝初始化,但拷贝初始化又需要调用拷贝构造,造成死循环),且任何额外的形参都有默认值。
有3种情况会调用拷贝构造函数:

  1. 通过使用一个已有的同类型对象来初始化新创建的对象A a2 = a1
  2. 对象作为参数传递给函数 如下面a2.get(a1)
  3. 从函数返回这个对象时会调用拷贝构造

下面分别使用代码来说明几种调用情况:

#include <iostream>
using namespace std ;
class A{
private:
    int _a ;
public:
    A(int a){
        _a = a ;
        cout<< "this is a's  constructor function"<< endl  ;
    }
    A(const A &a){
        cout << "this is a's copy constructor function" << endl ;
    }
    ~A(){
        cout << "this is a's destructor function" << endl ;
    }
    A getA(A a){
        return a ;
    }
    void   printA(){
        cout<< _a <<endl ;
    }

} ;
A constructor_aA(){
    A a(12) ;
    return a ;
}
int main(){
    A a1(10) ;
    a1.printA() ;
    cout << "====1======" <<endl ;
    //第一种情况,使用已初始化的对象初始化未初始化的对象的时候调用拷贝构造函数
    A a2 = a1 ;  //拷贝构造,区别以拷贝赋值的形式:   a2 = a1
    //第一种情况,使用已初始化的对象初始化未初始化的对象的时候调用拷贝构造函数,括号法
    A a3(a1);  //拷贝构造
    cout << "=====2=====" <<endl ;
    //第2种情况,复制对象把它作为参数传递给函数。
    a2.getA(a1) ;  //实际上发生的是  A a = a1 ; //拷贝构造,实际上还发生了一次      return的返回值会被拷贝构造给一个新的类对象,此处没有接收
    cout << "=====3=====" <<endl ;
    //第3种情况,函数返回一个对象
    A a4 = constructor_aA(); 
    cout << "==========" <<endl ;;
    return 0 ;
}
- 注意区分拷贝构造和拷贝初始化,初始化是行为,需要调用拷贝构造函数。
2. 拷贝赋值

拷贝赋值发生在下面的这种情况:

A a ,b ;
b = a ;
3.析构函数
一般情况下,需要析构函数的类都需要拷贝和赋值操作。
需要拷贝操作的类也需要赋值操作,反之亦然

=default 显示要求编译器生成合成的控制函数。只能用于拷贝控制函数
=delete将函数定义为删除的函数,表示虽然声明了该函数,但是不能使用。delete必须出现在函数第一次声明的时候。 可以将delete用于普通函数,表示该函数不能被调用。
-当不可能拷贝,赋值,销毁类的成员时,类的合成拷贝控制成员就被定义为删除的(不能拷贝赋值销毁的成员指1.析构函数不能访问,2.某个拷贝构造函数是删除的或private的3. 类的某个常用拷贝赋值运算符是删除的或private的。如果类的某个成员的析构函数是删除的或不可访问的,或是类有一个引用成员,没有初始化器。)其本质是类的数据成员不能默认拷贝赋值删除或销毁。

拷贝控制和资源管理

对象拷贝时行为有两种情况,一种是对象的拷贝时类的行为像值拷贝,每个对象有自己独立的状态。一种是像指针,副本和原对象使用相同的底层数据。改变副本也会改变愿对象。

上一篇 下一篇

猜你喜欢

热点阅读