拷贝构造函数

2018/03/11 C 共 2456 字,约 8 分钟

什么是拷贝构造函数

拷贝构造函数是一种特殊的构造函数,具有单个形参,该形参(常用const修饰)是对该类类型的引用。当定义一个新对象并用一个同类型的对象对它进行初始化时,将显示使用拷贝构造函数。当该类型的对象传递给函数或从函数返回该类型的对象时,将隐式调用拷贝构造函数。

class Person
{
public:

    Person(const Person& p){//拷贝构造函数
        return *this;
    }
    Person& operator=(const Person& p);//重载赋值操作符
    
};

拷贝构造函数和赋值函数的区别

拷贝构造函数是一个对象初始化一块内存区域,这块内存就是新对象的内存区,而赋值函数是对于一个已经被初始化的对象来进行赋值操作。

    Person t1;
    t1=f();//这是赋值函数

    Person t2=f();//这是复制构造函数

啥时候用拷贝构造函数

  1. 一个对象以值传递的方式传入函数体
  2. 一个对象以值传递的方式从函数返回
  3. 一个对象需要通过另外一个对象进行初始化。

以值传递的方式传入函数体

    f(Person t2){};
    f(t1);//将t1复制给t2,调用拷贝构造函数!

    f(){
        Person t3;
        return t3;//首先构造t3,构造函数,
        //然后将t3复制到一个临时对象,调用拷贝构造函数
    }

注意:下面这种情况在传参的过程中,没调用

Person(int a){}
    f(Person t1){

    }
    f(3);//这个传参过程中只调用了构造函数,没有调用拷贝构造函数,编译器会尽量减少多余的操作

以值传递的方式从函数返回

那就是说在返回的过程中会调用一次拷贝构造函数,那出现如下情况

    f(){
        Person t3;
        return t3;//首先构造t3,构造函数,
    }
    Person t4=f();
    //这调用拷贝函数,但只调用一次,而不是两次,省略了到临时对象的过程,所以次序为
    //构造函数t3,拷贝构造函数t4,析构t3

与之类似的,假如不是拷贝调用,是赋值函数

    f(){
        Person t3;
        return t3;//首先构造t3,构造函数,
    }
    Person t4;
    t4=f();
    //这明显是赋值函数,因此需要临时对象的参与,
    //次序为:构造函数t3,拷贝构造函数临时对象,赋值函数,析构函数t3,析构函数临时对象

还有种情况,这个f返回值没人要

    f(){
        Person t3;
        return t3;//首先构造t3,构造函数,
    }
    f();
    //这就是调用一次拷贝构造函数,构造了临时对象,然后没人要这个临时对象,自己析构了
    //次序为:构造函数t3,拷贝构造函数临时对象,析构函数t3,析构函数临时对象

部分代码测试

测试1


#include <iostream>
using namespace std;
class B
{
public:
    B(){cout<<"构造函数B"<<endl;}
    B(int i):data(i){cout<<"构造函数B"<<data<<endl;}
    B play(B b){
        cout<<"fwkj"<<endl;
        return b;
        }
    B(const B&b){
        cout<<"拷贝构造函数"<<endl;
    }
    ~B(){cout<<"析构函数B"<<endl;}
    B& operator=(const B& b){
        cout<<"等于号"<<endl;
        return *this;
    }
    private:
    int data;
};
int main()
{
    B temp;
    B t3;
    t3=temp.play(5);

    return 0;
}

结果:

构造函数B
构造函数B
构造函数B5
fwkj
拷贝构造函数
等于号
析构函数B
析构函数B
析构函数B
析构函数B

测试2

#include<iostream>
class TestConstructor
{
public:
	TestConstructor()
	{
		std::cout << "TestConstructor()" << std::endl;
	}
	~TestConstructor()
	{
		std::cout << "~TestConstructor()" << std::endl;
	}
	TestConstructor(const TestConstructor& testObj)
	{
		std::cout << "TestConstructor(const TestConstructor&)" << std::endl;
	}
	TestConstructor& operator = (const TestConstructor& testObj)
	{
		std::cout << "TestConstructor& operator = (const TestConstructor& testObj)" << std::endl;
		return *this;
	}
};
TestConstructor testFunc()
{
	TestConstructor testInFunc;  //3、调用TestConstructor() 生成对象testInFunc
	return testInFunc;           //4、调用TestConstructor(const TestConstructor&) 生成临时对象
								 //5、调用析构函数,析构对象testInFunc
}
int main()
{
	TestConstructor test;  //1、调用TestConstructor() 生成对象test
	test = testFunc();     //2、调用testFunc()    //6、调用等号把临时对象复制给对象test  //7、调用析构函数,析构临时对象
	return 0;              //8、调用析构函数,析构对象test
}

Search

    Table of Contents