copy构造函数也被称为赋值构造函数
class Test
{
public:
Test() //无参数构造函数
{
m_a = 0;
m_b = 0;
cout<<"无参数构造函数"<<endl;
}
Test(int a)
{
m_a = a;
m_b = 0;
}
Test(int a, int b) //有参数构造函数
{
m_a = a;
m_b = b;
cout<<"有参数构造函数"<<endl;
}
//赋值构造函数 (copy构造函数) //
Test(const Test& obj )
{
cout<<"我也是构造函数 " <<endl;
m_b = obj.m_b + 100;
m_a = obj.m_a + 100;
}
public:
void printT()
{
cout<<"普通成员函数"<<endl;
cout<<"m_a"<<m_a<<" m_a"<<m_b<<endl;
}
private:
int m_a;
int m_b;
};
C++中的copy构造函数有4种调用场景:
Test t1(1, 2);
//第1种调用方法
Test t2 = t1; //用t1来初始化 t2
t2.printT();
//第2种调用方法
Test t2(t1); //用t1对象 初始化 t2对象
t2.printT();
//第3种调用方法
//业务函数 形参是一个元素
void f(Test p)
{
cout<<p.GetX()<<endl;
}
f(t1); //t1实参取初始化形参p,会调用copy构造函数
//第4种调用方法
//g函数 返回一个元素
//结论1 : 函数的返回值是一个元素 (复杂类型的),
//返回的是一个新的匿名对象(所以会调用匿名对象类的copy构造函数)
//
//结论2: 有关 匿名对象的去和留
//如果用匿名对象 初始化 另外一个同类型的对象, 匿名对象 转成有名对象
//如果用匿名对象 赋值给 另外一个同类型的对象, 匿名对象 被析构
//
//你这么写代码,设计编译器的大牛们:
//我就给你返回一个新对象(没有名字 匿名对象)
Test g()
{
Test A(1, 2);
return A;
}
//
void objplay3()
{
//用匿名对象初始化m 此时c++编译器 直接把匿名对转成m(扶正) 从匿名转成有名字了m
Test m = g();
printf("匿名对象,被扶正,不会析构掉\n");
cout<<m.GetX()<<endl;;
}
void objplay4()
{
//用匿名对象 赋值给 m2后, 匿名对象被析构
Test m2(1, 2);
m2 = g();
printf("因为用匿名对象=给m2, 匿名对象,被析构\n");
cout<<m2.GetX()<<endl;;
}
当类中定义了拷贝构造函数时,c++编译器不会提供无参数构造函数;当类中定义了有参数构造函数是,c++编译器不会提供无参数构造函数
如果类中的属性有指针,则会出现深拷贝和浅拷贝的问题
class Name
{
public:
Name(const char *myp)
{
m_len = strlen(myp);
m_p =(char *) malloc(m_len + 1); //
strcpy(m_p, myp);
}
~Name()
{
if (m_p != NULL)
{
free(m_p);
m_p = NULL;
m_len = 0;
}
}
protected:
private:
char *m_p ;
int m_len;
};
//对象析构的时候 出现coredump
void objplaymain()
{
Name obj1("abcdefg");
//Name obj2 = obj1; //C++编译器提供的 默认的copy构造函数 浅拷贝
Name obj3("obj3");
obj3 = obj1; // C++编译器提供的 等号操作 也属 浅拷贝
}
上述代码在执行时,会出现浅拷贝问题
C++编译器在执行上述程序时,会使用编译器的默认拷贝构造函数,这个拷贝构造函数在执行时,会直接将obj1中指针的地址复制给obj2,而在执行西沟函数时,同一块内存空间被析构了两次,造成后面析构的指针变成了野指针,从而导致程序出错
//Name obj2 = obj1;
//解决方案: 手工的编写拷贝构造函数 使用深copy
Name(const Name& obj1)
{
m_len = obj1.m_len;
m_p = (char *)malloc(m_len + 1);
strcpy(m_p, obj1.m_p);
}