C++学习笔记(二十六):c++ 复制与拷贝构造函数
2024-01-10 01:27:55
- 本节介绍拷贝构造函数。
- 当我们复制数据或对象是一般情况下我们会有两个副本。但当我们仅需要读取数据或者修改一个已经存在的对象时,我们不想去复制一份副本,这样会造成性能的损耗。理解什么时候复制,什么时候不需要复制对提升程序的性能有较大的帮助。
- 接下来的示例展示复制操作以及不想复制的时候需要怎样去操作。
-
#include <iostream> #include <string> #include <memory> class Entity { public: int x, y; Entity(int x, int y) { this->x = x; this->y = y; std::cout << "这是构造函数!!!" << std::endl; } ~Entity() { std::cout << "这是析构函数!!!" << std::endl; } }; int main() { //Entity e1(2,5); //Entity e2 = e1; //e2.x = 9; //此时修改e2中属性变量的值不会影响e1,因为我们复制了一根Entity Entity *e1 = new Entity(2, 5); Entity* e2 = e1; e2->x = 4; //此时修改e2中属性变量的值会影响e1,因为我们复制了e1的地址到e2,它两指向同样的地址 std::cin.get(); return 0; }
-
手动实现String类来展示copy操作
-
#include <iostream> #include <string> #include <memory> //自己实现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]; //+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 s1 = "pcop"; /* 下面这种方式进行copy操作会导致程序崩溃,因为在此处=操作进行的是浅拷贝, 会导致两个String对象中的m_Buffer指向同一块内存地址,这样就会导致析构函数 会对同一块内存地址释放两次 */ String s2 = s1; std::cin.get(); return 0; }
#include <iostream> #include <string> #include <memory> //自己实现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]; //+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+1); } char& operator[] (int index) { return m_Buffer[index]; } ~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 s1 = "pcop"; /* * 如果不是先上诉的拷贝构造函数 下面这种方式进行copy操作会导致程序崩溃,因为在此处=操作进行的是浅拷贝, 会导致两个String对象中的m_Buffer指向同一块内存地址,这样就会导致析构函数 会对同一块内存地址释放两次 */ String s2 = s1; /* * 下面操作修改s2的时候s1的值也会修改,因为两个String对象的m_Buffer指向同一块内存 * 我们在复制中应该的操作是分配一块新的内存用来复制m_Buffer */ s2[2] = 'z'; //解决上诉方法可以通过深拷贝来完成,本示例中通过拷贝构造函数来实现 std::cout << s1 << std::endl; std::cout << s2 << std::endl; std::cin.get(); return 0; }
#include <iostream> #include <string> #include <memory> //自己实现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]; //+1是因为要添加一个空终止符 memcpy(m_Buffer, string, m_Size); m_Buffer[m_Size] = 0; } //拷贝构造函数 String(const String& other) :m_Size(other.m_Size) { std::cout << "Copy String!!!" << std::endl; m_Buffer = new char[m_Size+1]; memcpy(m_Buffer, other.m_Buffer, m_Size+1); } char& operator[] (int index) { return m_Buffer[index]; } ~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; } void PringString(const String& s) { std::cout << s << std::endl; } int main() { String s1 = "pcop"; /* * 如果不是先上诉的拷贝构造函数 下面这种方式进行copy操作会导致程序崩溃,因为在此处=操作进行的是浅拷贝, 会导致两个String对象中的m_Buffer指向同一块内存地址,这样就会导致析构函数 会对同一块内存地址释放两次 */ String s2 = s1; /* * 下面操作修改s2的时候s1的值也会修改,因为两个String对象的m_Buffer指向同一块内存 * 我们在复制中应该的操作是分配一块新的内存用来复制m_Buffer */ s2[2] = 'z'; //解决上诉方法可以通过深拷贝来完成,本示例中通过拷贝构造函数来实现 /* * 如果 PringString(String& s) 以下PringString方法调用的时候都会调用String的拷贝构造函数,每次需要分配新的内存 会造成很大的性能浪费,我们只是想直接打印PringString方法的参数,不想通过复制。 所以在PringString参数传递是直接传递引用 PringString(const String& s) */ PringString(s1); PringString(s2); std::cin.get(); return 0; }
文章来源:https://blog.csdn.net/qq_16701727/article/details/135408748
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!