拷贝控制操作

1 拷贝构造函数

如果一个构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数。
class Test
{
public:
	Test() = default;
	TEst(int m_x): m_x(x) { }
	Test(const Test &);		//拷贝构造函数
private:
	int m_x;
};

void runTest()
{
	Test t1;		//合成构造函数
	Test t2(5);		//直接初始化
	Test t3(t2);	//直接初始化,调用的也是拷贝构造函数
	Test t4 = t3;	//拷贝初始化
}

以下几种情况将会出现 拷贝初始化:

  1. 使用=定义变量时。
Test t1;
Test t2 = t1;
  1. 将一个对象作为实参传递给一个非引用类型的形参,即以值传递的方式。
void func(Test t);

Test t(5);
func(t);	//值传递方式,调用了Test的拷贝构造函数
  1. 从一个返回类型为非引用类型的函数返回一个对象。
Test func()
{
	Test t;
	return t;
}
Test t1 = func();	//值传递方式,调用了Test的拷贝构造函数
  1. 用花括号列表初始化一个数组中的元素或一个聚合类中的成员。

2 拷贝赋值函数

当用一个类的对象为另一个对象赋值时,会调用拷贝赋值函数。
拷贝赋值函数需要重载 =运算符,该函数通常返回一个指向其左侧运算对象的引用。其原因是为了能够连续赋值。
如果类没有定义拷贝赋值函数,编译器会为它生成一个合成拷贝构造赋值运算符。

class Foo
{
public:
Foo &operator=(const Foo&);	//赋值运算符
...
};

Foo f1;
Foo f2;
f2 = f1;	//调用拷贝赋值函数

3 析构函数

构造函数:初始化对象的非static数据成员。
析构函数:释放对象使用的资源,并销毁对象的非static数据成员。
在一个析构函数中,首先执行函数体,然后销毁对象。成员按初始化顺序的逆序销毁。

何时调用析构函数:
无论何时一个对象被销毁,就会自动调用其析构函数:

  1. 变量离开其作用域是被销毁。
  2. 当一个对象被销毁时,其成员被销毁。
  3. 容器(无论是标准容器还是数组)被销毁时,其元素被销毁。
  4. 对动态分配的对象,当对指向它的指正应用delete运算符时被销毁。
  5. 对于临时对象,当创建它的完整表达式结束时被销毁。

下面是各种构造函数,拷贝构造函数,拷贝复制函数,析构函数调用时机的例子:

struct X{
    X() {std::cout << "X()" << endl; }
    X(const X& x) {cout << "X(const X&)" << endl;}
    X& operator=(const X&){ cout << "X &operator=(const &x)" << endl;}

    ~X() {cout << "~X()" << endl;}
};

void func1(struct X x1, struct X &x2)   //引用和非引用作为形参
{

}

X func2(X &x1)  //对象值作为返回
{
    X x(x1);

    return x;
}

X &func3(X x)   //引用作为返回
{

    X x1(x);
    return x1;
}

int main()
{
    cout << "begin " << endl;
    {
        X x1;
        X *px1 = new X();
        X x2 = x1;  //拷贝初始化
        X x3;
        x3 = x1;    //拷贝赋值
        X x4(x1);   //直接初始化
        delete px1;
    }
    cout << "end!!\n" << endl;
    //作为容器元素
    cout << "vector" << endl;
    {

        vector<X> vx;   //竟然没有进行初始化
        vx.push_back(X());
        vx.push_back(X());

        // vector<X> vx2(vx);
       // vector<X> vx2(10);

    }
     cout << "vector end\n" << endl;
    //函数调用
    cout << "func begin" << endl;
    {
        X x1;
        X *px1 = new X();
        func1(x1, *px1);
        X x2 = func2(x1);   //直接接一个返回
        X x3;
        x3 = func2(x1);

        X x4 = func3(x1);
        X x5;
        x5 = func3(x1);

    }
     cout << "func end!!\n" << endl;
    return 0;
}

输出:

begin
X()
X()
X(const X&)
X()
X &operator=(const &x)
X(const X&)
~X()
~X()
~X()
~X()
~X()
end!!

vector
X()
X(const X&)
~X()
X()
X(const X&)
X(const X&)
~X()
~X()
~X()
~X()
vector end

func begin
X()
X()
X(const X&)
~X()
X(const X&)
X()
X(const X&)
X &operator=(const &x)
~X()
X(const X&)
X(const X&)
~X()
X(const X&)
~X()
X()
X(const X&)
X(const X&)
~X()
X &operator=(const &x)
~X()
~X()
~X()
~X()
~X()
~X()
func end!!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值