c++primer第十二章读书笔记

本章主要讲解new运算符在各种情况下的使用注意事项。
c++使用new和delete运算符来动态控制内存。

一、关于静态成员

(1)静态成员属于类,不属于对象,即在多个对象中只有一个静态成员对象副本。
(2)静态数据成员在类中声明,在包含类方法的文件中初始化。但如果静态成员是const整型类型或者枚举类型,则可以在类声明中初始化。
(3)静态成员函数由于没有this指针,因此只能访问静态成员。对象要通过作用域限定符来调用静态成员方法。

在自定义类String要考虑浅拷贝与深拷贝的问题,下面对自定义类中默认方法做个分析,要对函数做深拷贝和浅拷贝的考虑。
二、关于自定义类默认生成的函数
默认构造函数、默认析构函数、拷贝构造函数、赋值运算符、地址运算符

(1)默认构造函数:
带参数的构造函数也可以是默认构造函数,只要所有的参数都有默认值。
在构造函数中使用new分配内存,必须在相应的析构函数中使用delete来释放内存。

(2)拷贝构造函数
拷贝函数调用的三种情况。

  1. 新建一个对象并初始化化同类现有对象时,会调用拷贝构造函数。
String s1(s2);
String s1 = s2;
String s1 = String(s2);
String *p2 = new String(s2);
  1. 当函数按值传递时,会调用拷贝函数
  2. 返回局部对象时,会调用拷贝构造函数。

由于按值传递都将调用拷贝构造函数,因此应该按照引用来传递,提高效率。
默认拷贝构造函数逐个复制数据成员,复制的是成员的值,这样就会造成浅拷贝。
浅拷贝的指的是有复制数据成员指针的值,但没有为分配空间,造成两个指针指向同一块内存,使得析构函数
对这块内存释放了两次,因此对拷贝构造函数进行重载。

(3)赋值运算符

String s1 = s2;

关于这句代码可能有两种使用步骤:
一是初始化,直接调用拷贝构造函数。二是先调用拷贝构造函数,然后使用赋值运算符。

在自定义类型String中,关于赋值运算符要实现深拷贝。

三、在构造函数中使用new的注意事项:

1- 如果构造函数使用new来初始化指针成员,则应该在析构函数中使用delete
2- new对于delete ,new [ ] 对应delete [ ]
3- 多个构造函数中必须使用相同的方式使用new,但可以在一个构造函数中使用new,在另一个构造函数中将指针成员置空(c++新的特性使用nullptr表示空指针)

四、有关返回对象的说明

(1)返回指向const对象的引用,(不会调用拷贝构造函数)旨在提高效率。
(2)返回指向非const对象的引用,这里主要考虑对流运算符的重载(<< 或者 >>).
(3)返回对象,不能返回局部的引用。
(4)返回const对象,防止在if判断中将==写成=,改变对象的值,保护数据。

五、析构函数调用的情况
(1)对象是动态,执行完定义该对象的程序是,将调用对象的析构函数。
(2)如果对象时静态(外部、静态(外部)或者来着名称空间),程序解释时,调用析构函数
(3)如果对象时new创建的,显式调用delete删除对象,将调用析构函数,否则该对象的析构函数不会被调用。

六、关于placement new 运算符
palacement new
在已有的内存上分配空间,不分配空间,只是构造函数的调用。

void * operator new(size_t size,void *p)
{
     return p;
}

cahr buffer[1024]
Test *p2 = new(buffer) Test(200);//operator new(sizo_t ,void *p)
cout << p2->n_ <<endl;//placement new 不分配内存 + 构造函数。

自定义类String
String.h

#ifndef _String_H_
#define _String_H_

#include <iostream>
using namespace std;

class String
{
public:
    String(const char *s);
    String(const String &s);
    String &operator=(const String &s);
    String &operator=(const char *s);
    String();
    ~String();
    char & operator[](int i);
    const char & operator[](int i) const;

    friend bool operator<(const String &s1,const String &s2);
    friend bool operator>(const String &s1,const String &s2);
    friend bool operator==(const String &s1,const String &s2);
    friend ostream &operator<<(ostream &out,const String &st);
    friend istream &operator>>(istream &in,String &st);

    static int HowMany();
private:
    char *str;
    int len;
    static int num_strings; 
    static const int MAXSIZE = 80;
};

#endif //_STRING_H_

String.cpp

#include <iostream>
#include <cstring>
#include "StringBad.h"

using namespace std;

int String::num_strings = 0;

String::String(const char *s)
{
    len = strlen(s);
    str = new char[len + 1];
    strcpy(str,s);
    num_strings++;
//  cout << num_strings << ":" << str << "\"object created " << endl;

}
String::String(const String &s)
{
    num_strings++;
    len = s.len;
    str = new char[len + 1];
    strcpy(str,s.str);
//  cout <<num_strings << ": \"" << str << "\" object created" << endl;
}

String & String::operator=(const String & s)
{
//  cout << "operator = " << endl;
    if(this == &s)
    {
        return *this;
    }
    delete [] str;
    len = s.len;
    str = new char[len + 1];
    strcpy(str,s.str);
    return *this;
}
String & String::operator=(const char *s)
{
    delete [] str;
    len = strlen(s);
    str = new char[len + 1];
    strcpy(str,s);
    return *this;
}

String::String()
{
    len = 4;
    str = new char[1];
    str[0] = '\0';
    num_strings++;
//  cout << num_strings << ":" << str << "\"default object created" << endl; 
}

String::~String()
{
//  cout << "\"" << str << "\"object deleted, ";
    --num_strings;
//  cout << num_strings << endl;
    delete [] str;
}

bool operator<(const String &s1,const String &s2)
{
    return strcmp(s1.str,s2.str) < 0;
}

bool operator>(const String &s1,const String &s2)
{
    return s2 < s1;
}
bool operator==(const String &s1,const String &s2)
{
    return strcmp(s1.str,s2.str) == 0;
}

char & String::operator[](int i)
{
    return str[i];
}
const char & String::operator[](int i) const
{
    return str[i];
}

ostream & operator<<(ostream &out,const String &st)
{
    out << st.str;
    return out;
}

istream &operator>>(istream &in,String &st)
{
    char temp[80];
    in.get(temp,80);
    if(in)
    {
        st = temp; // operator=(const char *);
    }
    while(in && in.get() != '\n')
        continue;
    return in;
}

int String::HowMany()
{
    return num_strings;
}

main.cpp

#include <iostream>
#include "StringBad.h"

using namespace std;

void callme1(String &);
void callme2(String );
int main()
{
    String name;
    cin >> name;
    cout << name << endl;

    return 0;
}


void callme1(String &rsb )
{
    cout << "callme1 " << endl;

}

void callme2(String rsb)
{
    cout << "callem2" << endl;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值