拷贝控制

拷贝控制操作

  • 拷贝构造函数
  • 移动构造函数     // 用同类型的对象初始化本对象
  • 拷贝赋值运算符
  • 移动赋值运算符    // 将一个对象赋予同类型的另一个对象
  • 析构函数       // 销毁对象
    注意点:
    ①如果一个类没有定义所有这些拷贝控制成员,编译器会自动为它定义缺失的操作。
    ②声明后加=default来显示要求编译器生成合成的版本,只能对具有合成版本的成员函数使用(默认构造函数&拷贝控制成员)。
    ③声明后加=delete来定义删除的函数,来阻止该函数的调用,可以对任何函数使用,与=default不同。
    < utility >头文件中的move函数调用均采用std::move
    swap(a,b); //若ab均为内置类型,此时会调用标准库std::swap,否则按照匹配程度最优的调用

class A
{
public:
    A(const A &a){}                   // 拷贝构造函数
    A(const A &&a){}                  // 移动构造函数
    A& operator=(const A &a){}        // 拷贝赋值运算符
    A& operator=(const A &&a){}       // 移动赋值运算符
    ~A(){}                            // 析构函数
};

拷贝构造函数

定义:构造函数的第一个参数为自身类类型的引用,且任何额外参数都有默认值。编译器生成的合成拷贝构造函数为浅拷贝

使用拷贝构造函数的情况:

  1. 用=定义变量时               // Ta = b;
  2. 非引用参数传递              // fcn(T v); fcn(a); 这也是参数第一个为&的原因,否则出现死循环
  3. 非引用函数返回              // fcn(){… return v;}
  4. 列表初始化数组元素            // T arr[size] = {…}
  5. 容器元素用非emplace添加          // insert()|push()
  6. 直接初始化时编译器根据参数匹配调用    // T a(b);编译器使用普通函数匹配

拷贝赋值运算符

A a1,a2;
a1 = a2;          //将一个对象赋予同类型的另一个对象

合成的拷贝赋值运算符类似合成的拷贝构造函数。

析构函数

当变量离开作用域、对象销毁时成员销毁、容器销毁时其元素销毁、delete对象指针,析构函数调用,成员按初始化的逆序销毁。
一个类自定义了析构函数,基本也需要自定义拷贝赋值运算符和拷贝构造函数,反过来却不一定。

移动构造函数和移动赋值运算符

从给定对象窃取资源而不是拷贝资源(指针的移交,之前的指针变量需置nullptr),一般均声明为noexcept(不抛异常,置于参数列表与初始化列表开始的:中间)
如果一个类定义了自己的拷贝构造函数、拷贝赋值运算符或析构函数,编译器就不会为它合成移动构造函数和移动赋值运算符了。
移动迭代器解引用生成一个右值引用,通过调用标准库的make_move_iterator函数可将一个普通迭代器转换为一个移动迭代器。

copy(make_move_iterator(b),make_move_iterator(e),d);

简易的SmartPoint

template<typename T>
class SmartPoint
{
public:
    SmartPoint():users(new size_t(1)),p(new T()){}                        //默认构造函数
    explicit SmartPoint(T *q):users(new size_t(1)),p(q){}                 //内置指针构造函数
    SmartPoint(const SmartPoint &sp):users(sp.users),p(sp.p){++*users;}   //拷贝构造函数
    SmartPoint& operator=(const SmartPoint &sp);                          //赋值运算符重载
    ~ SmartPoint();                                                       //析构函数
private:
    size_t *users;
    T *p;
};
template<typename T>
SmartPoint<T>& SmartPoint<T>::operator=(const SmartPoint &sp)       
{
    ++*sp.users;    //先对右边指针引用计数+1,解决自我复制存在的问题
    if (--*users==0)
    {
        delete users;
        delete p;
    }
    users = sp.users;
    p = sp.p;
    return *this;
}
template<typename T>
SmartPoint<T>::~ SmartPoint()
{
    if (--*users==0)
    {
        delete users;
        delete p;
    }
}

引用限定符

  • 引用限定符可以为&&&(成员函数参数列表后),且必须同时出现在函数的声明和定义中。
  • 可以和const结合使用,const限定符置前,引用置后,二者均可以作为重载区分。
  • &表示仅能通过左值调用该函数,&&表示仅能通过右值调用该函数,const &均可。
  • 如果一个成员函数有引用限定符,则具有相同参数列表的所有版本都必须有引用限定符。

From: http://blog.csdn.net/zhanghuanzj/article/details/50704914

发表评论

电子邮件地址不会被公开。 必填项已用*标注

15 − 7 =

+ 79 = 81