IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++ Prime Plus 第12章 类和动态内存分配 -> 正文阅读

[C++知识库]C++ Prime Plus 第12章 类和动态内存分配

StringBad.h

#include <iostream>
#ifndef STRINGBAD_H
#define STRINGBAD_H
class StringBad
{
private:
    char* str;
    int len;
    //!静态变量所有类对象共享一份
    static int num_string;
public:
    StringBad();
    StringBad(const char* s);
    // StringBad(const StringBad& st);
    ~StringBad();
    friend std::ostream& operator<<(std::ostream& os,const StringBad& st);
};
#endif

StringBad.cpp

#include "./StringBad.h"
#include <cstring>
using namespace std;

//TODO 在这里对静态成员进行初始化 不能在类声明中初始化静态成员变量,因为声明只是描述如何分配内存,但不分配内存
//TODO 也不能放在头文件初始化,因为头文件一般会被其他文件包含,如果在头文件初始化,可能会出现多个初始化的副本导致错误
int StringBad::num_string = 0;

StringBad::StringBad(const char* s)
{
    len = strlen(s);
    str = new char[len+1];
    //拷贝字符串
    strcpy(str,s);
    num_string++;
    cout << num_string << ":" << str << "对象被创建" << endl; 

}

StringBad::StringBad()
{
    len = 4;
    str = new char[4];
    strcpy(str,"C++");
    num_string++;
    cout << num_string << ":" << str << "对象被创建" << endl; 
}
// StringBad::StringBad(const StringBad& st)
// {
// }
StringBad::~StringBad()
{
    cout << str << "对象被销毁,\t" ; 
    --num_string;
    cout << num_string << "个对象存在" << endl;
    delete []str;
}

std::ostream& operator <<(std::ostream& os,const StringBad& st)
{
    os << st.str;
    return os;
}

main.cpp

#include <iostream>
#include "StringBad.h"
using namespace std;
//TODO main()函数控制台输出
// 1:张飞对象被创建
// 2:李四对象被创建
// 3:王五对象被创建
// 引用传递:张飞
// 输出st1:张飞
// 值传递:李四
// 李四对象被销毁, 2个对象存在
// 输出st2:
// 3:C++对象被创建
// 张飞对象被销毁, 2个对象存在
// 王五对象被销毁, 1个对象存在
// �对象被销毁,    0个对象存在
// *** Error in `./main': double free or corruption (fasttop): 0x0000000000ab2070 ***
//!问题① error double free
//!问题② 输出st2本应该是李四 但是输出的是一个空值
//!问题③ 最后有乱码
//!引起问题的原因 调用了隐式的复制和赋值  解决方法显示的提供复制和赋值
void callme1(StringBad& st)
{
    cout << "引用传递:" << st << endl;
};
void callme2(StringBad st)
{
    cout << "值传递:" << st << endl;
};
int main()
{
    //TODO创建三个对象
    StringBad st1("张飞");
    StringBad st2("李四");
    StringBad st3("王五");
    callme1(st1);
    cout << "输出st1:" << st1 << endl;
    //!问题① 值传递传递的是参数的副本,会调用StringBad的复制构造函数,但是我们没有显示的提供复制构造函数,使用的是类提供的隐式复制
    //!它是一个浅复制,即复制的只是一个指针副本,指针的值还是指向传入参数的地址,那么在函数执行完之后讲自动执行析构函数释放掉内存,所以出现了两个问题
    //!一 st2的cout输出的一个空 二 在整个函数执行完之后,会再次调用st2的析构函数,这时候出现了乱码
    callme2(st2);
    cout << "输出st2:" << st2 << endl;
    //!创建一个新对象st4,并初始化为st3的值 这里调用的是复制构造
    StringBad st4 = st3;
    //!问题② 将一个已有的对象赋值给另一个对象时,讲会调用隐式的赋值运算符 问题跟隐式的复制构造一样,是一个浅复制
    StringBad st5;
    st5 = st1;
}

改进后的StringBad类

StringBad.h

#include <iostream>
#ifndef STRINGBAD_H
#define STRINGBAD_H
class StringBad
{
private:
    char* str;
    int len;
    //!静态变量所有类对象共享一份
    static int num_string;
public:
    StringBad();
    StringBad(const char* s);
    StringBad(const StringBad& st);
    ~StringBad();
    StringBad& operator=(const StringBad& st);
    friend std::ostream& operator<<(std::ostream& os,const StringBad& st);
};
#endif

StringBad.cpp

#include "./StringBad.h"
#include <cstring>
using namespace std;

//TODO 在这里对静态成员进行初始化 不能在类声明中初始化静态成员变量,因为声明只是描述如何分配内存,但不分配内存
//TODO 也不能放在头文件初始化,因为头文件一般会被其他文件包含,如果在头文件初始化,可能会出现多个初始化的副本导致错误
int StringBad::num_string = 0;

StringBad::StringBad(const char* s)
{
    len = strlen(s);
    str = new char[len+1];
    //拷贝字符串
    strcpy(str,s);
    num_string++;
    cout << num_string << ":" << str << "对象被创建" << endl; 

}

StringBad::StringBad()
{
    len = 4;
    str = new char[4];
    strcpy(str,"C++");
    num_string++;
    cout << num_string << ":" << str << "对象被创建" << endl; 
}
StringBad::StringBad(const StringBad& st)
{
    cout << "调用复制构造" << endl;
    num_string++;
    len = st.len;
    str = new char[len+1];
    //拷贝字符串
    strcpy(str,st.str); 
    cout << num_string << ":" << str << "对象被创建" << endl; 
}
StringBad::~StringBad()
{
    cout << str << "对象被销毁,\t" ; 
    --num_string;
    cout << num_string << "个对象存在" << endl;
    delete []str;
}

StringBad& StringBad::operator=(const StringBad& st)
{
    if(this == &st)
        return *this;
    delete [] str;
    len = st.len;
    str = new char[len+1];
    strcpy(str,st.str);
    return *this;
}

std::ostream& operator <<(std::ostream& os,const StringBad& st)
{
    os << st.str;
    return os;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-15 22:13:21  更:2022-03-15 22:17:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:06:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码