【45】C++的复制与拷贝构造函数
示例:string类的浅拷贝
#include <iostream>
#include <string>
class String
{
private:
char* m_Buffer;
unsigned int m_Size;
public:
String(const char* string)
{
m_Size = strlen(string);
m_Buffer = new char[m_Size + 1];
memcpy(m_Buffer, string, m_Size + 1); //memcpy(m_Buffer, string, m_Size);
// m_Buffer[m_Size] = '\0';
}
~String()
{
delete[] m_Buffer;
}
friend std::ostream& operator<<(std::ostream& stream, const string& string);
};
std::ostream& operator<<(std::ostream& stream, const string& string)
{
stream << string.m_Buffer;
return stream;
}
int main()
{
String string = "Cherno";
String second = string;
std::cout << string << second << std::endl;
return 0;
}
该程序运行完后,编译器会抛出异常(系统崩溃),这是由于second只是简单地复制了string的指针,即second与string都指向了同一个内存空间,当程序结束后,析构函数调用了两次,即释放了两次内存,这正是系统报错的原因。
在一般情况下,如果我们用旧对象复制构造生成新对象,C++会自动调用默认构造函数,执行浅拷贝操作 (简单地复制对象的内容)。
我们想要实现的是string和second各自都有内存空间,并且指向各自的内存空间,而不是指向同一段内存空间。
示例:string类的深拷贝
#include <iostream>
#include <string>
class String
{
private:
char* m_Buffer;
unsigned int m_Size;
public:
String(const char* string)
{
m_Size = strlen(string);
m_Buffer = new char[m_Size + 1];
memcpy(m_Buffer, string, m_Size + 1); //memcpy(m_Buffer, string, m_Size);
// m_Buffer[m_Size] = '\0';
}
String(const String& other)
: m_Size(other.m_Size)
{
m_Buffer = new char[m_Size + 1];
memcpy(m_Buffer, other.m_Buffer, m_Size);
}
~String()
{
delete[] m_Buffer;
}
char& operator[](unsigned int index)
{
return m_Buffer[index];
}
friend std::ostream& operator<<(std::ostream& stream, const string& string);
};
std::ostream& operator<<(std::ostream& stream, const string& string)
{
stream << string.m_Buffer;
return stream;
}
int main()
{
String string = "Cherno";
String second = string;
second[2] = 'a';
std::cout << string << std::endl; // Cherno
std::cout << second << std::endl; // Charno
return 0;
}
以上就是string类的深拷贝函数,当我们修改second的第二个字符时,我们会发现string并没有也进行修改,它们指向不同的内存空间。
另外,当我们要使用类来当做函数的形参时,首先要考虑在函数体是否要修改对象,如果不修改,一定要在对象的类型参数前加上const
,而且要加上&
(引用),来避免调用拷贝构造函数造成不必要的内存开销与时间。