这里写自定义目录标题
浅拷贝与深拷贝
浅拷贝是指拷贝构造函数简单的复制操作,在使用时可以由编译器完成。深拷贝是指在堆区重新开辟一片内存空间,进行拷贝操作。当类1的构造函数中用到了new方法开辟一个动态内存空间,且在析构函数中使用delete方法进行内存释放时,程序会出现问题。当使用浅拷贝方法将类1拷贝至类2时,编译器会逐字节地将类1的类容传给类2,包括开辟的内存地址。也就是说类1和类2共用了同一块动态内存。当使用完毕,调用析构函数时,类2首先使用delete关键字释放了该内存,而类1的析构函数还会执行一次delete,但是此时该内存已经释放了,造成堆区内存重复释放问题。
该问题通过深拷贝进行解决,就是自己写一个拷贝构造函数,重新开辟一片内存空间来存放类1中动态内存中存放的数据。
使用引用来接收返回的对象本体
当我们用到链式编程时,需要多次调用类方法,最常见的就是输入输出函数,cout << … << …<< endl,于是我们需要在方法函数结束时返回对象本体,以进行下一次方法调用。问题就在于我们接受这个返回时应该怎么接收?直觉上是返回一个对象就可以了,那么我们看一下如下代码以及输出:
class number
{
public:
int num;
public:
number(int num)
{
this->num = num;//this区分相同名字的变量
}
number Add(int num)
{
this->num += num;
return *this;
}
};
int main()
{
number x(10);
x.Add(10).Add(10);
cout << "新的x的值为:" << x.num << endl;
return 0;
}
我们可以看到,这个结果显然是不对的,新的x的应该是30。这是因为我们返回一个值时,编译器另外拷贝了一份对象进行返回,我们在第一次调用Add方法时,就出现了两个对象,分别是x和x’,x‘接收了*this,这两个对象的x.num与x’.num都加了10变成了20,但是在进行第二次Add方法调用时,调用的主体是x’而不是x了,所以我们在打印x.num时,自然就是20了。
为了解决这个问题,我们应该返回一个x的引用,操纵x所在内存上的值,如下面所示:
class number
{
public:
int num;
public:
number(int num)
{
this->num = num;//this区分相同名字的变量
}
number & Add(int num)
{
this->num += num;
return *this;
}
};
int main()
{
number x(10);
x.Add(10).Add(10);
cout << "新的x的值为:" << x.num << endl;
return 0;
}