36 - 经典问题解析三(赋值 string)

news2025/8/12 21:28:48

---- 整理自狄泰软件唐佐林老师课程

1. 关于赋值的疑问

什么时候需要重载赋值操作符?编译器是否提供默认的赋值操作?

  • 编译器为每个类 默认重载了赋值操作符
  • 默认的赋值操作符 仅完成 浅拷贝
  • 当需要进行 深拷贝必须重载赋值操作符
  • 赋值操作符与拷贝构造函数有相同的存在意义

1.1 编程实验:默认赋值操作符重载

#include <iostream>
#include <string>

using namespace std;

class Test
{
    int* m_pointer;
public:
    Test()
    {
        m_pointer = NULL;
    }
    Test(int i)
    {
        m_pointer = new int(i);
    }
    Test(const Test& obj)
    {
        m_pointer = new int(*obj.m_pointer);
    }
    Test& operator = (const Test& obj)
    {
        if( this != &obj )
        {
            delete m_pointer;
            m_pointer = new int(*obj.m_pointer);
        }
        
        return *this;
    }
    void print()
    {
        cout << "m_pointer = " << hex << m_pointer << endl;
    }
    ~Test()
    {
        delete m_pointer;
    }
};

int main()
{
    Test t1 = 1;
    Test t2;
    
    t2 = t1;
    
    t1.print();
    t2.print();
    
    return 0;
}

在这里插入图片描述

1.2 问题分析

在这里插入图片描述

  • 重载赋值操作符,必然需要实现深拷贝:
    在这里插入图片描述

1.3 一般性原则

重载赋值操作符,必然需要实现 深拷贝

1.4 编程实验:数组类的优化

#include "IntArray.h"

IntArray::IntArray(int len) {    m_length = len;    }

bool IntArray::construct() {
    bool ret = true;
    m_pointer = new int[m_length];
    if (m_pointer) {
        for(int i = 0; i < m_length; i++) {
            m_pointer[i] = 0;
        }        
    } else {
        ret = false;
    }
    return ret;
}

IntArray* IntArray::NewInstance(int len) {
    IntArray* ret = new IntArray(len);
    if (!(ret && ret->construct())) {
        delete ret;
        ret = 0;
    }
    return ret;
}

int IntArray::length() {    return m_length;    }

bool IntArray::get(int index, int& value) {
    bool ret = (0 <= index) && (index < length());
    if( ret ) {
        value = m_pointer[index];
    }
    return ret;
}

bool IntArray::set(int index, int value) {
    bool ret = (0 <= index) && (index < length());
    
    if( ret ) {
        m_pointer[index] = value;
    }
    return ret;
}

int& IntArray::operator [] (int index) {
    return m_pointer[index];
}

IntArray& IntArray::operator = (const IntArray& obj) {
    if (this != &obj) {
        int* pointer = new int[obj.m_length];

        if (pointer) {
            for (int i = 0; i < obj.m_length; i++) {
                pointer[i] = obj.m_pointer[i];
            }
            m_length = obj.m_length;
            delete[] m_pointer;
            m_pointer = pointer;
        }
    }
    return *this;
}

IntArray& IntArray::self() {
    return *this;
}

IntArray::~IntArray() {    delete[] m_pointer;    }
#ifndef _INTARRAY_H_
#define _INTARRAY_H_

class IntArray {
private:
    int m_length;
    int* m_pointer;
    IntArray(int len);
    bool construct();
public:
    static IntArray* NewInstance(int len);
    int length();
    bool get(int index, int& value);
    bool set(int index, int value);
    int& operator [] (int index);
    IntArray& operator = (const IntArray& obj);
    IntArray& self();
    ~IntArray();
};
#endif
#include <iostream>
#include <string>
#include "IntArray.h"

using namespace std;

int main() {
    IntArray* a = IntArray::NewInstance(5);
    IntArray* b = IntArray::NewInstance(10);

    if( a && b ) {
        IntArray& array = a->self();
        IntArray& brray = b->self();
        
        cout << "array.length() = " << array.length() << endl;
        cout << "brray.length() = " << brray.length() << endl;
    
        array = brray;
        
        cout << "array.length() = " << array.length() << endl;
        cout << "brray.length() = " << brray.length() << endl;
    }

    delete a;
    delete b;

    return 0;
}

在这里插入图片描述

1.5 编译器默认提供的函数

在这里插入图片描述

左边看起来是个空类,但实际编译器会 默认提供如上4个函数

2. 关于string的疑问1

下面的代码输出什么?为什么?
在这里插入图片描述

2.1 编程实验:字符串问题1

在这里插入图片描述

2.2 问题分析

在这里插入图片描述

  • string对象内部维护了一个指向数据的char* 指针,这个指针可能在程序运行的过程中发生改变

3. 关于string的疑问2

下面的代码输出什么?为什么?
在这里插入图片描述

3.1 编程实验:字符串问题2

在这里插入图片描述

3.2 问题分析

在这里插入图片描述

修改如下:
在这里插入图片描述

4. 小结

  • 在需要进行深拷贝的时候必须重载赋值操作符
  • 赋值操作符和拷贝构造函数有同等重要的意义
  • string类通过一个数据空间保存字符数据
  • string类通过一个成员变量保存当前字符串的长度
  • C++开发时尽量避开C语言中惯用的编程思想

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/33395.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Elasticsearch系列【1】概述

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 文章目录Elastic公司Elastic StackElasticsearch结构化/非结构化数据全文搜索ES 发展史ES 特点ES 应用场景ES 应用案例Beats 系列LogstashKibanaElastic公司 Elastic是一家以搜索引擎闻名世界的软件公司…

pythoin爬虫2之利用cookie进行登录

python爬虫2之利用cookie进行登录利用requests模拟post方法cookies的获取session综合实例拓展&#xff1a;实现时间间隔&#xff08;第一次抓取后间隔...秒进行下一次抓取&#xff09;利用requests模拟post方法 requests.post(url,data,hearders) url即要解析的网址data即是向服…

【学习笔记18】JavaScript对象的基本认识

一、什么是对象 &#xff08;一&#xff09;概念 &#x1f603; 就是一个数据的集合(复杂数据)&#x1f601; 对象属于复杂数据类型(引用数据类型) &#xff08;二&#xff09;知识点的补充 JS 的数据类型 1. 基本数据 2. 复杂数据&#xff08;引用数据类型&#xff09; 引用数…

图像处理技术:数字图像分割 ------ 图像分割、边界分割(边缘检测)、区域分割

一、图像分割概述 • 定义 是指根据灰度、彩色、空间纹理、几何形状等特征把图像划分 成若干个互不相交的区域&#xff0c;使得这些特征在同一区域内表现出一致 性或相似性&#xff0c;而在不同区域间表现出明显的不同 分割出来的区域应该同时满足&#xff1a; (1&#xff09…

opencv之修改尺寸、灰度转换(python)

1、修改图片大小 #修改图片大小 resize_img cv.resize(img,dsize(200,100)) 完整代码 import cv2 as cv img cv.imread("C:\\Users\\Administrator\\Desktop\\huge.jpg") #修改图片大小 resize_img cv.resize(img,dsize(200,100)) #显示修改后图片 cv.imshow(修改…

【单目标优化求解】贪婪非分级灰狼算法求解单目标优化问题(G-NHGWO)【含Matlab源码 2005期】

⛄一、贪婪随机自适应搜索算法简介 1 贪婪随机自适应搜索算法 GRASP算法分两个阶段&#xff0c;构造阶段和局部搜索阶段[3]。在构造阶段&#xff0c;初始化可行解S和候选集C&#xff0c;并对候选集的每一个元素进行评估&#xff0c;判断是否可加入限制候选列表&#xff08;Res…

西电通信技术基础实验

实验一 基带传输常用编码 实验内容 数字编码技术&#xff1a;AMI码、曼彻斯特编码、HDB3码 实验目的 掌握几种基带传输常用码型的编码规则&#xff0c;如AMI码、HDB3码、曼彻斯特码。然后利用MATLAB设计并实现它们的编码。 实验环境 MATLAB程序设计、MATLAB Simulink仿真…

IMX6ULL + SPI LCD(驱动IC ILI9341)显示简单的QT界面

1. 硬件&#xff1a; 使用正点原子的IMX6ULL Linux开发板 开发板底板原理图版本&#xff1a;V2.1 核心板原理图版本&#xff1a;V1.6 LCD &#xff1a;MSP2402 (IC ILI9341) 2. 查找可用引脚 开发板上引出的引脚是在JP6上&#xff0c;只看JP6会发现没有可用的SPI引脚&…

【前端内容学习】vue的引用,下载,语法

&#xff08;1&#xff09;vue的使用方式 原版本应该是三种使用方式&#xff0c;但是现在vue官网好像已经找不到关于本地下载的内容了 1&#xff0c;直接在官网上引用网络CDN文件&#xff0c;注意这种引用方式&#xff0c;要把这一段写在所有使用vue的部分前面 <script s…

蓝鲸研运体系在腾讯内的应用实践

蓝鲸是腾讯IEG十多年研运探索的经验与成果&#xff0c;积累了很多人的智慧与付出。由于腾讯IEG的业务特殊性&#xff0c;蓝鲸体系天生地展现出对异构业务的友好&#xff0c;避免了需要重复造轮子才能完成对多业务的支持。本次分享主要介绍蓝鲸研运体系在腾讯内的发展、应用及未…

【Linux】Linux常用命令

目录一.帮助命令1.man获取帮助信息2.help获取shell内置命令的帮助信息3.怎么判断命令的类型4.使用man查看内置命令5.常用快捷键二.文件目录类命令1.pwd 显示当前工作目录的绝对路径2.cd 切换路径3.ls 列出目录的内容4.mkdir 创建一个新的目录(文件夹)5.rmdir 删除目录(文件夹)6…

linux64/ubuntu20.04安装NVIDIA驱动详细过程

每次安装Nvidia驱动的时候都要查询&#xff0c;各种各样的教程可能也不大适合自己&#xff0c;故记录一下安装过程&#xff1b; 本人所使用的系统为ubuntu20.04&#xff0c;64bit&#xff1b; 1、查看是否存在nvidia的显卡信息 命令&#xff1a;lspci | grep NVIDIA 2、根据显…

奥迪Q3电瓶损坏问题解决思路

背景 最近自己的小Q3坏了&#xff0c;具体场景就是无钥匙进入感应不生效&#xff0c;所有钥匙按键失灵&#xff0c;通过机械钥匙可以开启门锁但是汽车完全无法启动&#xff0c;方向盘锁死&#xff0c;灯光没有反应。初步推断电瓶损坏&#xff0c;或者漏电导致完全亏电。 怎么判…

数理统计笔记6:假设检验

引言 数理统计笔记的第6篇先介绍了假设检验&#xff0c;给出了各种常用的假设检验的方法&#xff0c;最后介绍了用置信区间和p值来进行假设检验的方法。 引言假设检验描述什么是假设什么是假设检验假设检验的基本思想假设检验的步骤假设检验的原理假设检验的两类错误双侧检验和…

【微电网优化】粒子群优化算法的微电网调度(光伏、储能、电动车、电网交互)【含Matlab源码 2190期】

⛄一、粒子群算法求解电联供型微电网经济运行优化简介 0 引言 热电联供 (combined heat and power, CHP) 系统建立在能源梯级利用的概念基础上, 统一解决了电能和热能的供应问题, 是一种经济节能、环境友好的用能方式, 具有良好的社会和经济效益, 在国内外引起广泛关注。在发展…

ShareSDK for Flutter

前言 这是一个基于ShareSDK功能的扩展的Flutter插件。使用此插件能够帮助您在使用Flutter开发应用时,快速地实现社会化功能,例如第三方授权登录,获取用户信息以及社交平台的分享等功能。 Demo例子&#xff1a;https://github.com/MobClub/ShareSDK-For-Flutter 开始集成 引入…

C++ 语言学习 day11 复习(3)

1.第一个是昨天的作业&#xff1a; 用类实现一个双向循环链表&#xff0c; 完成对应的功能&#xff0c;&#xff08;增删查改 &#xff09; 代码&#xff1a; list.h #ifndef LIST_H #define LIST_H #include <iostream> #include <string.h> using namespace s…

WebRTC入门教学和一对一通话实现

WebRTC入门学习 简介 大体架构 互联网实时通信平台&#xff0c;html5标准之一&#xff0c;使用简单的API就可以实现音频通信。 紫色部分的是Web应用开发者需要关注的部门&#xff0c;也就是WebRTC提供给开发者的接口蓝色部分是提供给浏览器厂商的接口&#xff0c;浏览器厂…

2023年天津理工大学中环信息学院专升本专业课报名考试须知

天津理工大学中环信息学院 2023年高职升本科专业课考试须知 根据《2023年天津市高职升本科招生实施办法》的相关要求&#xff0c;为做好高职升本科专业考试的报考工作&#xff0c;全面服务考生&#xff0c;保障考生权益&#xff0c;结合疫情防控要求&#xff0c;现将考试具体事…

14天学习训练营之 入门Pygame

目录 学习知识点 pygame 的 “hello world” pygame 模块概览 事件 理解事件 事件检索 处理鼠标事件 处理键盘事件 事件过滤 产生事件 模板代码 写一个把所有发生的事件输出的程序 使用方向键来移动图片 产生一个完全自定义的全新事件 这个程序让 “hello world”…