尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
c++面向对象之对象的赋值详解
对象初始化构造函数和复制构造函数在设计一个类时往往要设计构造函数。一般对象的初始化使用构造函数初始化如果没有构造函数则会使用默认构造函数。还可以用复制构造函数来通过一个已有对象初始化一个新的对象。设计一个类来表现对象的初始化复制构造以及赋值。在Stack.hpp头文件中声明类的成员。123456789101112131415161718//Stack.hpp#pragma onceclassStack {public:Stack(intmax_size);~Stack();//复制构造函数Stack(constStack s);boolIsEmpty()const;boolIsFull()const;voidPush(intdata);voidPop();intTop()const;private:int* buffer_;int* top_;intcapacity_;};在Stack.cpp中实现类中的方法。包括有一个表示大小的参数的构造函数析构函数拷贝构造函数栈空栈满的判断函数以及Push、Pop、Top等方法。1234567891011121314151617181920212223242526272829303132333435363738//Stack.cpp#include Stack.hpp#include iostreamStack::Stack(intmax_size) :capacity_(max_size),//buffer_(new int[max_size]),buffer_(static_castint*(std::malloc(sizeof(int) * max_size))),top_(buffer_) {}Stack::~Stack() {std::free(buffer_);}Stack::Stack(constStack s) :capacity_(s.capacity_),buffer_(static_castint*(std::malloc(sizeof(int) * s.capacity_))),top_(buffer_ - s.buffer_ s.top_) {std::memcpy(buffer_, s.buffer_,sizeof(int) * s.capacity_);}boolStack::IsEmpty()const{returntop_ buffer_;}boolStack::IsFull()const{returntop_ buffer_ capacity_;}voidStack::Push(intdata) {if(this-IsFull())throwStack is full!;*top_ data;}voidStack::Pop() {if(this-IsEmpty())throwStack is Empty!;top_--;}intStack::Top()const{if(this-IsEmpty())throwStack is Empty!;return*(top_ - 1);}在主函数前引用Stack.hpp头文件。创建一个s1对象并push两个值在使用拷贝构造复制s1创建对象s2。确认s1和s2的栈顶相等。在s2中push一个新的值s1和s2的栈顶变得不相等。创建新的对象s3再使用类默认的赋值运算符重载给s3赋值为s1。这样的赋值会把栈中的指针属性的地址直接复制到新的对象。在给 s3 push 了新的值之后s1、s3的 top_ 属性变得不相等但是s1、s3的buffer却指向同一区域在程序结束调用析构时会重复释放同一块内存造成报错。12345678910111213141516171819//OverloadAssignment#include iostream#include Stack.hppintmain() {Stack s1(16);s1.Push(1);s1.Push(2);Stack s2 s1;//调用复制构造函数std::cout s1 top: s1.Top() std::endl;std::cout s2 top: s2.Top() std::endl;s2.Push(3);std::cout s2 pushed 3 std::endl;std::cout s1 top: s1.Top() std::endl;std::cout s2 top: s2.Top() std::endl;Stack s3(16);s3 s1;//调用赋值运算符重载std::cout s3 top: s3.Top() std::endl;//观察报错信息s3的析构函数被调用了两次说明s3和s1指向了同一块内存区域导致内存被重复释放了。}虽然能够正常输出所有结果但是在程序结束后析构对象时由于重复释放相同空间引发报错。12345678910s1 top: 2s2 top: 2s2 pushed 3s1 top: 2s2 top: 3s1 top: 2s3 top: 2s3 pushed 3s1 top: 2s3 top: 3针对报错copilot的分析简短结论错误 程序在 std::free(buffer_) 处触发断点/崩溃。根本原因是对象复制后发生了浅拷贝——s3 s1; 使用了编译器生成的默认赋值运算符类声明只有拷贝构造函数未定义 operator导致 s1 和 s3 共享同一 buffer_ 指针程序结束时两次释放同一内存double free/堆破坏因此 free 抛出异常/断点。为什么会发生200字 Stack 定义了自定义拷贝构造函数会分配新缓冲区但没有自定义拷贝赋值运算符编译器生成的默认 operator 做逐成员赋值把 buffer_ 指针从 s1 拷贝到 s3浅拷贝。当两个对象析构时会重复释放同一块内存或在赋值后原对象的缓冲区被提前释放或覆盖导致堆损坏free 崩溃。重载赋值运算符如果需要对自定义对象赋值就需要重载赋值运算符。在Stack.hpp中声明重载赋值运算符的函数。并在Stack.cpp中完成。1234567891011121314//重载赋值运算符//函数的返回值是一个引用指向当前对象。在s3 s2 s1;这样的链式赋值中s2 s1的结果是s2的引用然后s3 s2实际上是s3 (s2 s1)因此s3最终也会得到s1的值。Stack Stack::operator (constStack s) {//给自己赋值if(this s)return*this;//释放原有资源std::free(buffer_);capacity_ s.capacity_;buffer_ static_castint*(std::malloc(sizeof(int) * s.capacity_));top_ buffer_ - s.buffer_ s.top_;std::memcpy(buffer_, s.buffer_,sizeof(int) * s.capacity_);return*this;}赋值函数的返回值是一个引用指向当前对象。在s3 s2 s1;这样的链式赋值中s2 s1的结果是s2的引用然后s3 s2实际上是s3 (s2 s1)因此s3最终也会得到s1的值。再去运行之前的主函数就不会发生重复释放内存的报错了。这样的赋值函数参数是自己的类型如果不手动实现会隐含一个默认的方法。这样的赋值函数叫做拷贝赋值函数。与拷贝构造函数相似都是传递一个自身的const引用类型。除了拷贝赋值函数也存在一般的赋值函数以一个复数类为例1234567891011classComplex {public:Complex(doubler,doublei) : real_(r), imag_(i) {};Complex operator (doubler) {real_ r;imag_ 0.0;return*this;}private:doublereal_, imag_;};隐式构造除此之外如果类中没有声明赋值函数但是存在有一个参数的构造函数也可以用隐式构造的方法使用等号给对象赋值。1234567891011121314151617classComplex {public:Complex(doubler) : real_(r), imag_(0.0) {};Complex(doubler,doublei) : real_(r), imag_(i) {};public:doublereal_, imag_;};intmain() {Complex c1(1, 2);//使用了隐式构造函数Complex c2 45.0;//使用了隐式构造函数c1 4;std::cout c1.real_ c1.imag_ i std::endl;std::cout c2.real_ c2.imag_ i std::endl;return0;}如果不希望使用隐式构造可以在构造函数前加explicit关键字explicit翻译是明确的、不加掩饰的计算机中是显式的意思加上explicit的构造函数无法被隐式调用。比如在Stack类中构造函数可以被隐式调用但是这种用法意义不明确如果不希望实现这种用法可以在构造函数前加上explicit。12345678classStack {public:explicitStack(intmax_size);//……intmain (){Stack st(16);st 20;//会报错}比如在复数类中同时定义了另一个构造函数此时使用隐式构造会产生歧义导致程序无法运行可以把这个有两个参数且有初值的构造函数指定为explicit。1234567891011121314151617classComplex {public:Complex(doubler) : real_(r), imag_(0.0) {};explicitComplex(doubler 0,doublei 0) : real_(r), imag_(i) {};public:doublereal_, imag_;};intmain() {Complex c1(1, 2);//使用了隐式构造函数Complex c2 45.0;//使用了隐式构造函数c1 4;std::cout c1.real_ c1.imag_ i std::endl;std::cout c2.real_ c2.imag_ i std::endl;return0;}这样可能没什么意义因为给了初值的构造函数可以用单个参数隐式构造也可以用多个参数隐式构造。12345678910111213141516171819classComplex {public:Complex(doubler 0,doublei 0) : real_(r), imag_(i) {};public:doublereal_, imag_;};intmain() {Complex c1(1, 2);//使用了隐式构造函数Complex c2 45.0;//使用了隐式构造函数c1 4;std::cout c1.real_ c1.imag_ i std::endl;std::cout c2.real_ c2.imag_ i std::endl;//使用多个参数的隐式构造c1 { 45, 56 };std::cout c1.real_ c1.imag_ i std::endl;return0;}到此这篇关于c面向对象对象的赋值的文章就介绍到这了
RELATED

相关推荐

C++中各种初始化方式示例详解

C++中各种初始化方式示例详解

本文主要给大家介绍了关于C初始化方式的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。C小实验测试:下面程序中main函数里a.a和b.b的输出值是多少?1234567891011121314151617181920212223#…

📅 2026/10/4 11:53:02
C++11中long long类型的具体使用

C++11中long long类型的具体使用

、引言在计算机编程的世界里,整数类型是最基础且常用的数据类型之一。随着计算机技术的不断发展,处理大规模数据和进行高精度计算的需求日益增长,传统的整数类型如int和long在表示范围上逐渐显得力不从心。为了满足这一需求,C11标…

📅 2026/10/4 11:53:02
Spring Boot集成OAuth2客户端实现SSO单点登录实战

Spring Boot集成OAuth2客户端实现SSO单点登录实战

1. 为什么业务系统要以OAuth2客户端身份接入SSO1.1 常见单点登录方案的对比与选型在做SSO单点登录之前,我先梳理了市面上几种常见的方案。以我这次遇到的实际场景为例:公司里有多个Java后端系统,每个系统各自维护一套用户表和登录逻辑&#x…

📅 2026/10/4 11:53:02
MORE NEWS

更多资讯

📰

AI Agent 架构设计与实战:从核心原理到并发避坑指南

1. 从零理解 AI Agent:它到底是什么,能帮你做什么很多人第一次听到 AI Agent 这个词,脑子里浮现的是科幻电影里那种能自己思考、自己行动的机器人。实际上,当下我们说的 AI Agent,本质上是以大语言模型为大脑&#xff…

📰

基于STM32的仓库环境控制系统:温湿度粉尘监测与ESP8266上云

1. 从仓库管理的真实痛点说起做仓储管理的人都有一个共识:货物损坏的原因里,温湿度失控和粉尘超标占了相当大的比例。特别是存放电子元器件、精密仪器、食品原料、药品这类对存储环境敏感的货物,一旦温湿度超出安全区间,轻则性能下…

📰

拼多多新店访客多少正常?2026最新阶段标准+流量优化实操指南

很多拼多多新手商家开店后,最焦虑的问题就是店铺访客太少:刚上架产品没访客是不是店铺废了?每天几十访客算不算正常?同行几百访客自己差距在哪?其实拼多多新店访客没有统一固定数值,核心看开店周期、运营动…

📰

GPT4 Turbo的128K上下文实测:从推特评测到斯坦福论文,TaoToken统一Key复现长上下文验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

告别Claude Cowork!用DeepSeek+LangGraph手搓免费编程Agent(附源码)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

LLM之Agent(五十七)|Claude Code 智能体循环:从入门到精通的实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬