浅复制
复制类对象时只是单纯的复制所有的值,如指针只会复制指针的大小,而不会再开辟同一空间大小的内存,即两个指针指向同一片内存空间。
伪代码:
class MyString
{
private:
char*buffer;
public:
MyString(const char* initString);
~MyString();
};
MyString::MyString(const char* initString) {
buffer= nullptr;
if(initString!= nullptr)
{
buffer=new char[strlen(initString)+1];
strcpy(buffer,initString);
}
}
MyString::~MyString() {
std::cout<<"clearing up"<<std::endl;
delete[] buffer;
}
void UseMyString(MyString str)
{
return;
}
int main() {
MyString sayHello("Hello from String Class");
UseMyString(sayHello);
return 0;
}
解释:
不同指针指向同一块内存地址,对同一块内存地址多次delete会导致系统崩溃。
使用复制构造函数确保深复制
即复制构造函数是一个重载的构造函数,每当对象被复制时,编译器将自动调用复制构造函数。
伪代码:
MyString::MyString(const char* initString) {
buffer= nullptr;
if(initString!= nullptr)
{
buffer=new char[strlen(initString)+1];
strcpy(buffer,initString);
}
}
MyString::MyString(const MyString &say) {
buffer= nullptr;
if(say.buffer!= nullptr)
{
buffer=new char[strlen(say.buffer)+1];
strcpy(buffer,say.buffer);
}
}
解释:
在复制对象的时候,编译器自动调用复制构造函数,即会从新new一个空间然后将原来对象的值复制过来。
注意:
1、复制构造函数的参数必须按引用传值,否则复制构造函数将不断调用自己,直到耗尽为 止。
2、类包含原始指针成员(如char*)时,务必编写复制构造函数和复制赋值运算符。
3、编写复制构造函数时,务必将接受源对象的参数时声明为const引用。
4、声明构造函数时,务必声明explicit避免隐式转换
5、务必将类成员声明为std::string和智能指针类型(而非原始指针类型),因为它们实现了 复制构造函数数,减少了工作量。
不到万不得已,类成员不使用原始指针。