拷贝构造函数
同一个类的对象在内存中有完全相同的结构,如果作为一个整体进行复制或称拷贝是完全可行的。
这个拷贝过程只需要拷贝数据成员,而函数成员是共用的(只有一份拷贝)。在建立对象时可用同一类
的另一个对象来初始化该对象的存储空间,这时所用的构造函数称为拷贝构造函数(Copy
Constructor)。
using namespace std;
class Empty
{
private:
int value1;
int value2;
public:
Empty() {}//构造函数
~Empty() {}//析构函数
Empty(const Empty&) {}//拷贝构造函数
};
在类中如果没有显式给出拷贝构造函数时,则C++编译器自动给出一个缺省的拷贝构造函数。
using namespace std;
class Empty
{
private:
int value1;
int value2;
public:
Empty(int x, int y) :value1(0) { value1 = x; value2 = y; }//构造函数
~Empty() {}//析构函数
void print()const
{
cout << "value1= " << value1 << "value2= " << value2 << endl;
}
};
int main()
{
Empty a(2, 2);
Empty b(33, 10);
Empty c(0, 0);
Empty d(b);
d.print();
return 0;
}
打印结果:
如果我们给出了拷贝构造函数,那么则按函数重载的规律,调用合适的构造函数。
using namespace std;
class Empty
{
private:
int value1;
int value2;
int value3;
//const char *a = "hello";
public:
Empty(int x, int y) :value1(0) { value1 = x; value2 = y; }
~Empty() {}
Empty(const Empty& x) :value1{ 3 }, value2{ 3 }
{
//value1 = x.value1;
//value2 = x.value2;
}
void print()const
{
cout << "value1= " << value1 << "value2= " << value2 << endl;
}
};
int main()
{
Empty a(2, 2);
Empty b(33, 10);
Empty c(0, 0);
Empty d(a);
//c = a + b;
d.print();
return 0;
}
打印结果value1=3,value2=3。
class Empty
{
private:
int value1;
int value2;
public:
Empty() {}
Empty(int x,int y) :value1(0) { value1 = x; value2 = y; }//构造函数
~Empty() {}//析构函数
Empty(const Empty&) {}//拷贝构造函数
Empty& operator+(const Empty& x)
{
Empty tmp (x.value1 + value1, x.value2 + value2);
return tmp;
}//运算符重载函数:等号的赋值重载
Empty* operator &() { return this; }//取地址函数
const Empty* operator &()const { return this; }//引用运算符的重载:取地址
void print()const
{
cout <<"value1= "<< value1 <<"value1= "<< value2 << endl;
}
};
Empty &fun(int x, int y)//此处的返回值为什么不能是对象
{
Empty tmp(x,y);
return tmp;
}
int main()
{
Empty a(2,2);
Empty b(3,0);
Empty e;
e = fun(1234,5678);
e.print();
return 0;
}
using namespace std;
#if 1
class Complex
{
private:
int _Real;
int _Image;
public:
Complex(int r = 0, int i = 0) :_Real(r), _Image(i)
{
cout << "Create Complex" << this << endl;
}
~Complex() { cout << "Destroy Complex" << this << endl; }
Complex(const Complex& cx) :_Real(cx._Real),_Image(cx._Image)
{
cout << "Copy Create Complex" << this << endl;
}
void show()
{
cout << "_Real = " << _Real << " _Image = " << _Image << endl;
}
Complex operator=(const Complex & cx)
{
if (this != &cx)
{
_Real = cx._Real;
_Image = cx._Image;
}
cout << "opreator =" << endl;
return *this;
}
};
int main()
{
Complex c1(1, 2);
Complex c2(c1);
Complex c3;
c3 = c2;
c3.show();
return 0;
}
下图输出的是 赋值重载函数返回值不加引用的情况:
Complex operator=(const Complex & cx)
blog.csdnimg.cn/fc7250602e174f8980bff704860c1b47.png)" />
而下图是 赋值重载函数返回值加引用的情况:
Complex & operator=(const Complex & cx)
由对比可以发现,当赋值重载函数返回值是对象时,当函数消亡之前,在主函数栈帧中创建一个临时的对象,把这个对象的成员一一赋值给C3后此临时对象就死掉了。
而当赋值重载函数返回值是对象的引用时,在函数退出之前不会创建一个临时对象,只返回对象(此this指针)的地址。
深拷贝和浅拷贝注意,当以引用返回时,一定注意此返回值是在哪儿定义的。当函数的生存期结束不影响此返回对象时,可以以引用返回。
在这里插入代码片深赋值和浅赋值
class MyString
{
char* str;
public:
MyString(const char* p = nullptr)
{
if (p != nullptr)
{
int n = strlen(p) + 1;
str = new char[n];
strcpy_s(str, n, p);
}
else
{
str = new char[1];
str[0] = ' ';
}
cout << "Create MyString" << this << endl;
}
~MyString()
{
delete[]str;
str = nullptr;
cout << "Destroy MyString: " << this << endl;
}
MyString(const MyString& s)
{
int n = strlen(s.str) + 1;
str = new char[n];
strcpy_s(str, n, s.str);
cout << "Copy Create MyString: " << this << endl;
}
void Print() const
{
cout << str << endl;
}
MyString & fun()
{
MyString tmp("hello");
return tmp;
}
int main()
{
MyString s1;
s1.Print();
s1 = fun();
s1.Print();
return 0;
}
我们可以看到这里打印的不是hello而是随机值。为什么?
当我们用fun()函数去初始化s1时,函数结束返回时以引用的方式,返回的是一个地址,当函数结束,栈帧归还给系统。再次调用时这个地址就是一个悬空指针,所以打印随机值。



