当前位置: 首页 > news >正文

中国电信网站备案英文外链平台

中国电信网站备案,英文外链平台,现货市场交易平台,如何搭建一个服务平台#x1f525;个人主页#xff1a;Quitecoder #x1f525;专栏#xff1a;c笔记仓 朋友们大家好啊#xff0c;本篇内容带大家深入了解拷贝构造函数 目录 1.拷贝构造函数1.1传值调用的无限调用1.2浅拷贝1.3深拷贝1.4深拷贝的实现 1.拷贝构造函数 拷贝构造函数是一种特殊的… 个人主页Quitecoder 专栏c笔记仓 朋友们大家好啊本篇内容带大家深入了解拷贝构造函数 目录 1.拷贝构造函数1.1传值调用的无限调用1.2浅拷贝1.3深拷贝1.4深拷贝的实现 1.拷贝构造函数 拷贝构造函数是一种特殊的构造函数在对象需要以同一类的另一个对象为模板进行初始化时被调用。它的主要用途是初始化一个对象使其成为另一个对象的副本 我们先引用前面所用到的日期类的例子 class Date { public:Date(int year 1, int month 1, int day 1){_year year;_month month;_day day;} private:int _year;int _month;int _day; };简单来说假如我现在定义了一个日期对象 int main() {Date d1(2005, 6, 23);return 0; }我需要定义一个d2与我的d1的数据相同如何定义呢 方法如下 int main() {Date d1(2005, 6, 23);Date d2(d1);return 0; }这里用到了拷贝构造那么拷贝函数是如何实现的呢我们接下来来探讨一下 拷贝构造函数通常声明为接受一个对同一类对象的常量引用参数 class ClassName { public:ClassName(const ClassName other); };参数const ClassName other是对另一个同类型对象的引用使用const确保不会无意中修改other。函数体在函数体内部你可以决定如何复制other对象的成员到新对象中。对于简单的情况这可能仅仅是复制每个成员变量的值。对于涉及动态分配内存或其他资源的类可能需要进行深拷贝 下面来探讨上述的Date类的实现 class Date { public:Date(int year 1, int month 1, int day 1){_year year;_month month;_day day;}Date(const Date d){_year d._year;_month d._month;_day d._day;} private:int _year;int _month;int _day; }; int main() {Date d1(2005, 6, 23);Date d2(d1);return 0; }拷贝构造函数是构造函数的一个重载形式,拷贝构造函数的参数只有一个且必须是类类型对象的引用使用传值方式编译器直接报错因为会引发无穷递归调用,这个我们后面进行讲解 Date(const Date d){_year d._year;_month d._month;_day d._day;}这里的d2就相当于thisd1就是另一个参数 1.1传值调用的无限调用 我们上面提到拷贝构造函数参数只有一个且必须是类类型对象的引用那么如果我使用传值调用会有什么结果呢 我们下面先来进行简单的铺垫 void fun1(Date d) {} void fun2(Date rd) {} int main() {Date d1(2005, 6, 23);fun1(d1);fun2(d1);return 0; }构造两个函数他们的参数不同第一个函数为传值传参在c语言中我们知道传值传参是一个拷贝的过程即把d1的值拷贝给dc规定自定义类型的拷贝都会调用拷贝构造 我们进行调试 在这里按F11我们目的是进入fun1函数这里却跳入拷贝构造函数 再按f11才会进入fun1函数中 大概过程如下 传值传参需要调用拷贝构造 fun2函数可以直接进入 在上述讲解后我们来探讨如果拷贝函数是传值引用会发生什么 调用拷贝构造需要传参这里传值传参就会调用一个新的拷贝构造 所以这里也是我们为什么只能用引用传参 1.2浅拷贝 class Date { public:Date(int year 1, int month 1, int day 1){_year year;_month month;_day day;}void Print(){cout _year - _month - _day endl;} private:int _year;int _month;int _day; }; int main() {Date d1(2005, 6, 23);Date d2(d1);d1.Print();d2.Print();return 0; }我们现在屏蔽掉拷贝构造看会发生什么 若未显式定义编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象内置类型成员按内存存储按字节序完成拷贝这种拷贝叫做浅拷贝或者值拷贝 那如果有自定义类型呢 我们看下面的代码 class Time { public:Time(){_hour 1;_minute 1;_second 1;}Time(const Time t){_hour t._hour;_minute t._minute;_second t._second;cout Time::Time(const Time) endl;} private:int _hour;int _minute;int _second; }; class Date { private:// 基本类型(内置类型)int _year 2024;int _month 1;int _day 1;// 自定义类型Time _t; }; int main() {Date d1;Date d2(d1);return 0; }在这个代码示例中我们有两个类Time 和 Date。Date 类中包含了一些基本类型的成员变量_year, _month, _day和一个自定义类型的成员变量_t一个 Time 类型的对象。当创建 Date 类的对象时不仅会初始化其基本类型的成员变量也会调用其自定义类型成员的构造函数来初始化 函数的调用过程 Date 对象的默认构造函数调用当 Date 类的对象被创建时它的默认构造函数编译器自动生成的因为没有显式定义会被调用。由于成员变量 _year, _month, _day 在类定义中已经被直接初始化编译器将这些初始化纳入默认构造函数的操作中。 Time 成员的构造函数调用在 Date 的构造函数执行过程中会自动调用 _tTime 类型的成员变量的默认构造函数来初始化 _t。Time 的默认构造函数设置 _hour, _minute, _second 为 1并不打印任何信息。 拷贝 Date 对象当 Date d2(d1); 执行时d2 是通过拷贝构造函数初始化的。因为 Date 类没有显式定义拷贝构造函数编译器会为它生成一个默认的拷贝构造函数。这个默认的拷贝构造函数会逐个拷贝 Date 类中的所有成员变量包括基本类型和自定义类型的成员。 对于基本类型成员如 _year, _month, _day直接进行值的复制对于自定义类型的成员_t会调用该成员的拷贝构造函数Time 类中定义的 Time(const Time)来进行拷贝。在这个过程中Time 的拷贝构造函数会输出信息Time::Time(const Time) 因此在执行 Date d2(d1); 时调用过程如下 首先调用 Date 的默认拷贝构造函数自动生成来初始化 d2。在初始化 d2 的过程中对于其自定义类型成员 _t调用 Time 的拷贝构造函数来初始化此时会输出 Time::Time(const Time)。 这就是自定义类型成员在 Date 类拷贝过程中构造函数的调用情况其他的基本类型成员变量则是通过简单的值复制来初始化的 在编译器生成的默认拷贝构造函数中内置类型是按照字节方式直接拷贝的而自定义类型是调用其拷贝构造函数完成拷贝的 如果我们删掉Time的默认的拷贝构造函数呢 class Time { public:Time(const Time t){_hour t._hour;_minute t._minute;_second t._second;cout Time::Time(const Time) endl;} private:int _hour;int _minute;int _second; }; class Date { private:// 基本类型(内置类型)int _year 2024;int _month 1;int _day 1;// 自定义类型Time _t; }; int main() {Date d1;Date d2(d1);return 0; }拷贝构造本身就是一种构造函数所以编译器不会生成默认构造函数 在这个代码中由于 Time 类中没有显式定义一个无参数的默认构造函数只定义了一个拷贝构造函数而 Date 类的实现依赖于 Time 类的这个默认构造函数来初始化其 _t 成员所以编译器将尝试调用 Time 类的默认构造函数时会失败因为找不到合适的构造函数来初始化 _t 当尝试创建 Date 类的实例 d1 时Date 类的默认构造函数由编译器隐式生成会被调用。默认构造函数会尝试初始化所有成员变量对于基本类型的成员变量 _year,_month, _day由于它们已经在类定义中直接初始化不会有问题。但对于 _tTime 类型的成员变量编译器需要调用 Time 类的默认构造函数来初始化它。由于 Time类中没有定义无参数的默认构造函数编译过程中会出现错误 当尝试通过拷贝构造函数创建 d2 时Date d2(d1);同样会遇到问题。虽然 Date 类的拷贝构造函数编译器自动生成的会尝试逐个拷贝所有成员变量对于 _t它会尝试调用 Time类的拷贝构造函数这部分没有问题。但在创建 d1 时已经失败因此这一步也无法成功执行 c也可以加入这串代码进行强制生成 Time() default;1.3深拷贝 如果你没有为类显式定义拷贝构造函数C编译器会自动生成一个默认的拷贝构造函数。默认拷贝构造函数会逐个复制对象的所有成员浅拷贝。对于基本数据类型和指向动态分配内存的指针成员这意味着只复制指针值而不复制指针指向的数据 我们来看下面的代码 typedef int DataType; class Stack { public:Stack(size_t capacity 10){_array (DataType*)malloc(capacity * sizeof(DataType));if (nullptr _array){perror(malloc申请空间失败);return;}_size 0;_capacity capacity;}void Push(const DataType data){// CheckCapacity();_array[_size] data;_size;}~Stack(){if (_array){free(_array);_array nullptr;_capacity 0;_size 0;}} private:DataType* _array;size_t _size;size_t _capacity; }; int main() {Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2(s1);return 0; }我们没有提供拷贝构造函数编译器默认提供我们来看运行结果 程序崩溃我们进行调试观察 当通过 Stack s2(s1); 这样的语句创建一个 Stack 类的对象时如果没有显式定义拷贝构造函数C 编译器会提供一个默认的拷贝构造函数它进行浅拷贝。这意味着 _array 指针的值被复制过来但指向的内存空间没有被复制。这会导致多个对象共享同一块内存空间进而导致双重释放等问题 类中如果没有涉及资源申请时拷贝构造函数是否写都可以一旦涉及到资源申请时则拷贝构造函数是一定要写的否则就是浅拷贝 **浅拷贝Shallow Copy**只复制对象的顶层结构如果对象中包含指针指向动态分配的内存则副本的这些指针将指向与原始对象相同的内存地址。这意味着两个对象共享部分资源。浅拷贝通常是通过默认的拷贝构造函数和赋值操作符实现的深拷贝则复制对象所有的层级结构。对于对象内部的每一个指针指向的内存深拷贝都会在堆上分配新的内存然后将原始数据复制到这块新分配的内存中。这样原始对象和副本对象将拥有完全独立的数据副本 1.4深拷贝的实现 深拷贝需要我们手动实现对于上述的代码我们需要手动补充于对象内部的每个指向动态分配内存的指针都需要 为副本分配新的内存空间。将原始对象指针指向的数据复制到新分配的内存中 typedef int DataType; class Stack { public:Stack(size_t capacity 10){_array (DataType*)malloc(capacity * sizeof(DataType));if (nullptr _array){perror(malloc申请空间失败);return;}_size 0;_capacity capacity;}//注意这里s2是thiss是s1Stack(const Stack s){DataType* tmp (DataType*)malloc(sizeof(DataType) * s._capacity);if (tmp nullptr){perror(malloc fail);exit(-1);}memcpy(tmp, s._array, sizeof(DataType) * s._size);_array tmp;_size s._size;_capacity s._capacity;}void Push(const DataType data){// CheckCapacity();_array[_size] data;_size;}~Stack(){if (_array){free(_array);_array nullptr;_capacity 0;_size 0;}} private:DataType* _array;size_t _size;size_t _capacity; }; int main() {Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2(s1);return 0; }//注意这里s2是thiss是s1Stack(const Stack s){DataType* tmp (DataType*)malloc(sizeof(DataType) * s._capacity);if (tmp nullptr){perror(malloc fail);exit(-1);}memcpy(tmp, s._array, sizeof(DataType) * s._size);_array tmp;_size s._size;_capacity s._capacity;}这个拷贝构造函数的主要功能是创建一个新的 Stack 对象该对象是对现有 Stack 对象称为 s的深拷贝。深拷贝意味着新对象将拥有与原对象相同的数据副本但这些数据存储在新分配的内存中。这样两个对象的状态互不影响修改一个对象的内容不会影响另一个 内存分配 使用 malloc 根据原栈 (s) 的容量 (_capacity) 分配足够的内存空间来存储数据副本。这里的内存大小是 s._capacity * sizeof(DataType) 数据复制 使用 memcpy 将原栈 (s) 的数据 _array 复制到新分配的内存 tmp 中。复制的长度是 s._size * sizeof(DataType)即仅复制原栈中实际存在的元素 更新成员变量 将新栈的 _array 指针更新为指向新分配的内存 tmp。 将新栈的 _size 和 _capacity 设置为与原栈 (s) 相同的值。这样保证了新栈在逻辑上与原栈完全相同拥有相同数量的元素和相同的容量 这下我们的问题也就解决了 class myqueue {private:Stack st1;Stack st2; }; int main() {myqueue q1;myqueue q2(q1);return 0; }有一个 Stack 类它实现了一个简单的栈并提供了深拷贝功能。然后创建一个 myqueue 类它内部使用了两个 Stack 实例。在 main 函数中创建了一个 myqueue 对象 q1 并尝试使用 q1 来初始化另一个 myqueue 对象 q2。这里的关键点在于理解 Stack 的深拷贝实现如何影响 myqueue 对象的复制行为 myqueue 类及其复制行为 myqueue 类内部包含两个 Stack 对象st1 和 st2。当使用一个 myqueue 对象来初始化另一个如 myqueue q2(q1);时myqueue 的隐式或默认拷贝构造函数被调用。C 默认的拷贝构造函数会逐个复制类的成员使用各成员自己的拷贝构造函数。因此q1 中的 st1 和 st2 会使用它们各自的深拷贝构造函数来初始化 q2 中的 st1 和 st2 由于 Stack 类已经提供了深拷贝的实现myqueue 类中的 st1 和 st2 成员在 myqueue 对象被复制时也会被深拷贝。这意味着 q1 和 q2 中的 st1 和 st2 在内存上是独立的q1.st1 和 q2.st1 指向不同的内存区域q1.st2 和 q2.st2 同理。因此q1 和 q2 在逻辑上是完全独立的队列它们内部的栈互不影响 隐式拷贝构造函数myqueue 类在这段代码中并没有显式定义自己的拷贝构造函数。它依赖于 C 自动生成的默认拷贝构造函数来正确地复制其成员。这在 Stack 提供深拷贝的情况下是安全的 本篇内容到此结束感谢大家观看
http://www.zqtcl.cn/news/256419/

相关文章:

  • 泉州哪个公司网站做的好百度反馈中心
  • 宽屏蓝色企业网站源码软件工程师英文
  • 中企动力网站建设公司网站的设计路线
  • 宠物网站制作内容正规货源网站大全
  • 网站建设pc端软件公司简介
  • 科技公司企业网站源码如何免费建购物网站
  • 用动物做网站名甘肃省城乡建设网站
  • 重庆网站制作长沙榆林网站建设
  • 加快政务公开网站建设在中企动力工作的感受
  • 佛山网站搜索排名宿迁新站seo
  • 上海免费网站建设公司南通高端网站
  • 网站被镜像 站长学院那个网站都有做莱的图片
  • 个人简历 网站开发做同城网站需要哪些手续
  • 建网站的公司南京网站权重是什么
  • 网站建设策略百度云域名没有备案怎么做网站
  • 档案网站建设图片网站名查找
  • 九亭镇村镇建设办官方网站好看的网站设计公司
  • 怎样建立门户网站怎么用wordpress模板
  • 潍坊专业建站wordpress建个人博客
  • 手把手网站开发网站建设违法行为
  • 网站模板插件做网站要审批吗
  • 建立网站如何盈利有哪些做室内设计好用的网站有哪些
  • 商城网站设计服务商网站开发时的闭包写法
  • 福建永安建设局网站如何在百度免费发布广告
  • 网站建设要用到哪些应用工具国际新闻最新消息今天2024年
  • 网站代码怎么打开门户网站建设目的
  • 个人网站开发项目总结做网站模板的网页名称是m开头
  • 响水哪家专业做网站win wordpress
  • 做图标去什么网站找微网页制作软件手机版
  • 网站开发源程序网页宣传方案