贵阳建站模板企业网站建立的失败案例
贵阳建站模板,企业网站建立的失败案例,中国外协加工网免费,网站建设的误区在上一篇《C 浅拷贝 vs 深拷贝#xff1a;从 0 开始一步一步讲透#xff08;Student 示例含判断方法#xff09;》里#xff0c;我们已经明确了结论#xff1a;
默认拷贝#xff08;编译器生成#xff09;对资源类通常是浅拷贝资源类想安全#xff0c;就要自己实现深拷…在上一篇《C 浅拷贝 vs 深拷贝从 0 开始一步一步讲透Student 示例·含判断方法》里我们已经明确了结论默认拷贝编译器生成对资源类通常是浅拷贝资源类想安全就要自己实现深拷贝或禁止拷贝 / 使用标准库替代这篇进阶主要解决三个“工程里一定会遇到”的点为什么拷贝赋值要先 delete 再 new自赋值怎么处理为什么std::string不会出浅拷贝问题移动语义到底解决什么Rule of Five 是什么1拷贝赋值为什么要先delete再new先回顾拷贝赋值发生的场景Student s1(Tom, 18); Student s2(Jack, 20); s2 s1; // s2 已经存在1.1 如果你不先释放旧资源会发生什么s2原本有一块堆内存保存 Jack。如果你直接new一块新内存覆盖namename new char[...]; // 覆盖了旧指针那么旧的那块内存就“丢失了地址”再也释放不了 →内存泄漏。所以拷贝赋值正确顺序必须是先释放旧资源再申请新资源再复制内容。1.2 为什么要做“自赋值保护”自赋值s1 s1;如果你不判断代码会这样走delete[] name;把自己资源删了然后还想从other.name拷贝其实就是自己已经被删掉的那块内存结果就是未定义行为可能崩可能乱码因此标准写法必须带上if (this other) return *this;2深拷贝赋值的标准写法可直接套用Student operator(const Student other) { if (this other) return *this; delete[] name; // 1) 释放旧资源 age other.age; name new char[strlen(other.name) 1]; // 2) 申请新资源 strcpy(name, other.name); // 3) 拷贝内容 return *this; }记住拷贝构造不用先 delete因为对象刚出生没旧资源拷贝赋值必须先 delete因为对象早就有资源了。3为什么std::string不会出浅拷贝问题上一节我们用char*是为了把“资源管理”的坑暴露出来。工程中你更应该写成这样#include string class Student { public: std::string name; int age; };然后Student s1; s1.name Tom; Student s2 s1; // 拷贝构造 Student s3; s3 s1; // 拷贝赋值不会崩溃原因很简单std::string自己就是一个资源管理类RAII它内部已经把析构 / 拷贝 / 移动 都实现好了。所以你拷贝Student时std::string会自动做正确的事情该深拷贝时深拷贝该移动时移动自动释放资源不会 double free结论能用标准库容器/字符串就别手写new/delete管字符串。4移动语义它不是“更安全”而是“更快”深拷贝是安全的但可能很贵大字符串/大数组拷贝成本高。移动语义解决的是避免复制大块数据改为“转移资源所有权”。4.1 直觉理解拷贝给你“复印一份资料”移动把“资料原件”直接交给你原来的那份清空因此移动通常不分配新内存不复制大量数据性能很好5Rule of Three vs Rule of Five一定要记住Rule of Three三法则如果你需要自定义这三个之一通常就要考虑另外两个析构函数~T()拷贝构造T(const T)拷贝赋值T operator(const T)因为这意味着你在“手动管理资源”。Rule of Five五法则C11 之后加入了移动语义所以资源类通常还要考虑移动构造T(T)移动赋值T operator(T)实战经验大多数时候你用std::string / vector / unique_ptr就不需要自己写五件套标准库已经替你做了。6工程建议三种策略怎么选当你写一个“资源类”时通常三种选择策略 A实现深拷贝像上一篇 Student 那样适用确实需要“复制一份独立资源”成本代码多、容易写错策略 B禁止拷贝资源独占比如文件句柄、锁、socket 通常不希望被复制Student(const Student) delete; Student operator(const Student) delete;策略 C用标准库类型替代裸指针最推荐std::string替代char*std::vector替代手写动态数组std::unique_ptr管理独占资源这是最不容易出错、工程最常用的路线。7一句话总结进阶版拷贝构造/拷贝赋值只是“什么时候拷贝”浅/深拷贝才是“怎么拷贝”资源类拷贝赋值必须自赋值保护 先释放旧资源再申请新资源工程里优先用std::string / vector / 智能指针把深拷贝坑交给标准库处理移动语义解决的是“性能”让资源转移比复制更高效C 对象拷贝 / 移动 速查表项目触发时机对象状态是否分配新内存性能成本是否需要手写典型用途拷贝构造函数T(const T)创建新对象时用另一个对象初始化新对象刚出生深拷贝时会中等资源类建议手写T b a;拷贝赋值运算符operator已有对象被另一个对象覆盖对象已存在深拷贝时会中等资源类必须手写b a;移动构造函数T(T)创建新对象时接收临时对象新对象刚出生通常不会很低可选性能优化T b std::move(a);移动赋值运算符operator(T)已有对象接收临时对象对象已存在通常不会很低可选性能优化b std::move(a);“人话理解版”类型本质行为类比拷贝构造复制资源复印一份资料拷贝赋值先丢旧资料再复印新资料覆盖旧文件移动构造转移资源所有权把原件直接交给你移动赋值先丢旧资料再接收原件把旧文件扔掉接收原件