C++Primer Plus(第六版)第十二章学习笔记:

本章主要内容

  • 对类成员使用动态内存分配
  • 隐式和显式复制构造函数
  • 隐式和显式重载赋值运算符
  • 构造函数使用new
  • 使用静态类成员
  • 定位new运算符用于对象
  • 使用指向对象的指针
  • 实现队列抽象数据类型

12.1 动态内存和类

先复习用new分配内存
head

#include <iostream>
#ifndef GOLF_H_INCLUDED
#define GOLF_H_INCLUDED


class StringBad
{
private:
    char * str;
    int len;
    static int num_string;
public:
    StringBad(const char * s);
    StringBad();
    ~StringBad();
    friend std::ostream & operator<<(std::ostream & os, const StringBad & st);
};

#endif // GOLF_H_INCLUDED

definition

// contain function called in file1
#include <cstring>
#include "golf.h"
rsing std::cout;

int StringBad::num_string = 0;

StringBad::StringBad(const char * s)
{
    len = std::strlen(s);
    str = new char[len + 1];
    std::strcpy(str, s);
    num_string++;
    cout << num_string << ":\"" << str << "\" object created\n";
    
} 

StringBad::StringBad()
{
    len = 4;
    str = new char[4];
    std::strcpy(str, "C++");
    num_string++;
    cout << num_string << ":\"" << str << "\" default object created\n";
}

StringBad::~StringBad()
{
    cout << "\"" << str << "\" object deleted, ";
    --num_string;
    cout << num_string << " left\n";
    delete [] str;
}

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

这个程序的运行结果有很大问题,因为会不加计数君而调用构造函数,调用的是复制构造函数。

12.1.2 特殊成员函数

C++会自动提供几个成员函数

  • 默认构造
  • 默认析构
  • 复制构造
  • 赋值运算符
  • 地址运算符
    编译器会生成后三个函数的定义
    为了使这复制构造和赋值运算符可以更好的工作,需要使用深度复制,即手动显示实现这两者。
//显式重载赋值,给被赋值对象单独的内存,只传递字符串的值过去,而不是两者指向同一个地址
StringBad & StringBad::operator=(const StringBad & st)
    {
    if(this == &st)
        return *this;
    delete []str;
    len = st.len;
    str = new char [len + 1];
    std::strcpy(str, st.str);
    return *this;
    }
//显式实现复制构造函数,帮助复制构造创建新的内存块并且更新静态部分
StringBad::StringBad(const StringBad & st)
{
    num_string++;
    len = st.len;
    str = new char [len + 1];
    std::strcpy(str, st.str);
    cout << num_string << ": \"" << str << "\"object created\n";
}

12.3 使用new时的注意事项

  • new和delete要对应
  • 同个类中的所有构造函数分配内存的格式需相同
  • 用0或nullptr来表示空指针
  • 深度复制的两个应用

12.4 有关返回对象的说明

  • 返回指向const对象的引用
  • 返回指向非const对象的引用
  • 返回对象
  • 返回const对象

12.5 使用指向对象的指针

就是普遍的那几种使用指针的方法

  • 直接声明
  • 指向现有对象,就是赋值为现有对象的地址
  • new一个新的对象,将其地址赋值给指针,此时会调用构造函数
12.5.3 定位new运算符复习

定位new运算符会分配内存时指定分配的位置
在程序中使用是有两点注意

  • 第二个定位对象会覆盖在第一个的位置
  • delete整个缓冲区的时候不会调用其中的对象的析构函数
    原因及解决方法
  • 第一个必须手动将位置右移,保证不会覆盖
  • 第二个因为delete只能用于常规new,不与定位new匹配,解决方法是显式为需要销毁的对象创造析构函数

12.6 复习

  • 重载<<运算符,返回的是ostream的引用
  • 转换函数,应该用explicit关键字来避免隐式调用
  • 构造函数使用new的类,几个new就几个delete,种类要匹配,还有深度赋值函数的定义

各种ADT专门拿一章来整理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值