期末复习c++知识点大回顾,八篇文章让你永不破防(建议收藏)

Posted 行码棋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了期末复习c++知识点大回顾,八篇文章让你永不破防(建议收藏)相关的知识,希望对你有一定的参考价值。

目录总览

c++知识点复习最全整理(一)

c++知识点复习最全整理(二)

c++知识点复习最全整理(三)

c++知识点复习最全整理(四)

c++知识点复习最全整理(五)

c++知识点复习最全整理(六)

c++知识点复习最全整理(七)

c++知识点复习最全整理(八)

目录

五、运算符重载

1.运算符new,delete介绍

1.1.new申请空间

1.2.delete释放空间

2.运算符重载

2.1.相关问题

2.2.常见运算符重载示例


五、运算符重载

1.运算符new,delete介绍

1.1.new申请空间

形式:

指针变量 = new<数据类型>[长度]

  •  申请一个整型(int)空间
int *ptr;
ptr = new int;
  •  申请一个整型空间并且初始化
int *ptr;
ptr = new int(5);
  • 申请长度为20的一维数组,但不能进行初始化
int *p;
p = new int[10];

注意:

  • 当分配的长度为1个单位时,可以省略方括号里面的整数。
int *int_ptr = new int;
//等价形式
int *int_p = new int[1];
  • 使用new分配空间时,方括号里面的数值可以是常量,也可以是变量。还可以是数值表达式。
int size = 10;
//常量
int *np = new int[5];
//变量
int *np1 = new int[size];
//表达式
int *np2 = new int[size+10];
  •  使用new分配的空间是连续的,可以使用指针访问分配空间里面的每一个元素。
int *p = new int[20];

//将第11个元素赋值为100
p[10] = 100;
//或者
*(p+10) = 100;
  •  如果当前存储器无法分配更多的内存空间,new运算符返回值为0(NULL)

1.2.delete释放空间

 delete释放空间只有两种形式:

//1
delete p;
//2
delete []p;

delete 释放new分配的单个对象指针指向的内存

delete[] 释放new分配的对象数组指针指向的内存

其实两种方式区别不大,主要区分在类中体现。

1.针对简单类型(int,float,long,double,char,struct等)

使用new分配后的无论是数组还是非数组形式内存空间用两种方式均可

如:

 int *a = new int[10];
 delete a;
 //或delete [] a; 

此种情况中的释放效果相同 原因在于分配简单类型内存时,内存大小已经确定,系统可以记忆并且进行管理,在析构时,系统并不会调用析构函数,

2.对于类class来说,两种方式体现出差异。

A *a = new A[10];
delete a;
//仅释放了a指针指向的全部内存空间 但是只调用了a[0]对象的析构函数 剩下的从a[1]到a[9]这9个用户对应内存空间将不能释放从而造成内存泄漏
delete [] a;
//释放了a指针指向的全部内存空间 并且调用使用类对象的析构函数释放用户自己分配的内存空间

注意:

①用new运算符获得的内存空间,只许使用一次delete,不允许多次对同一块空间进行多次释放,否则将会产生严重错误。

②delete只能用来释放由new运算符分配的动态内存空间,对于程序中的变量、数组的存储空间,不得使用delete运算符去释放。

2.运算符重载

运算符重载是通过定义函数实现的,即定义一个重载运算符的函数,在需要执行被重载的运算符时,系统自动调用该函数,以实现相应的运算。

运算符重载实质上是函数的重载。

重载形式:

函数类型 operator 运算符名称 (形参表列)   { 对运算符的重载处理 }

2.1.相关问题

  • 运算符能否进行重载

可以重载的运算符

+    -    *    /    %    ^    &    |    ~ !    =    <    >    +=    -=    *=    /=    % ^=    &=    |=    <<    >>    >>=    <<=    ==    != <=    >=    &&    ||    ++    --    ->*    ‘    -> []    ()    new    delete    new[]    delete[]

 不能重载的运算符

Operator

Name

.

类属关系运算符 

.*

成员指针运算符 

::

作用域运算符 

? :

条件运算符 

#

编译预处理符号 

sizeof()

取数据类型的长度 

  •  运算符重载不能创造新的运算符号,例如不能创建@@表示幂运算
  • 重载的运算符保持运算符的一些性质不变(优先级,结合性,操作个数,语法结构)
  • 赋值运算符(=)和地址运算符(&)不需要重载

 运算符重载函数一般采用两种方式:

  • 成员函数的形式
  • 友元函数的形式

运算符函数是一种特殊的成员函数或友员函数(全局函数通常被指定为友元函数)

2.2.常见运算符重载示例

+,- 运算符,以复数的运算为例:

#include<bits/stdc++.h>
using namespace std;

class Complex
{
private:
    double real,imag;//实部和虚部
public:
    Complex(double r=0,double i=0):real(i),imag(i){}//构造函数
    Complex operator +(const Complex &a);//重载+运算符
    Complex operator -(const Complex &a);//重载-运算符
    void print();
};
//定义为成员函数,可以访问类内的私有变量
Complex Complex::operator +(const Complex&a)
{
    Complex temp(real+a.real,imag+a.imag);
    return temp;
}
Complex Complex::operator -(const Complex&a)
{
    Complex temp(real-a.real,imag-a.imag);
    return temp;
}
void Complex::print()
{
    cout<<real<<" ";
    if(imag!=0)
    {
        if(imag>0) cout<<"+ ";
        cout<<imag<<"i\\n";
    }
}
int main()
{
	Complex t1(1,2);
    Complex t2(2,3);
    t2 = t1 + t2;//对象的赋值
    t2.print();
	return 0;
}

++ ,--重载

#include<bits/stdc++.h>
using namespace std;

class number
{
private:
    int num;
public:
    number(int n=0):num(n){};
    number& operator++();//前置自增
    number operator++(int);//后置自增
    void print();
};
number& number::operator++()
{
    num++;
    return *this;//前置自增要保证先增加,然后返回增加后的数据,所以返回类型是引用类型
}
number number::operator++(int)//int为形式参数,不参与实际运算
{
    number temp(*this);//保存临时的变量
    num++;//自增1
    return temp;//返回之前保存的没有进行加自增的变量
}
void number::print()
{
    cout<<num<<endl;
}
int main()
{
    number n1(2);
    n1++;
    n1.print();
    ++n1;
    n1.print();
    return 0;
}

1、运算符前置自增运算符 , 用成员函数实现时,没有形式参数。  

2、运算符后置自增运算符 ,另外增加一个形式上的形式参数,类型定为int。

这个参数只是用来区别两种自增算符,并不参加实际的运算。

<< 和>>运算符重载

#include<iostream>
using namespace std;
class Complex
{
private:
    double real,imag;
public:
    Complex(double r=0,double i=0):real(r),imag(i){}
    friend istream& operator >> (istream& in,Complex &c);
    friend ostream& operator << (ostream& out,Complex c);
};
istream& operator >> (istream& in,Complex &c)
{
    cout<<"请输入实部和虚部\\n";
    in >> c.real >> c.imag;
    return in;
}
ostream& operator << (ostream& out,Complex c)
{
    if(c.real!=0)
    {
        out << c.real ;//实部输出
        if(c.imag==0)
        {
            out << 0 << '\\n';
            return out;
        }
        else if(c.imag>0)
        {
            out << "+" << c.imag <<"i\\n";
            return out;
        }
        else 
        {
            out << c.imag << "i\\n";
            return out;
        }
    }
}
int main()
{
	Complex cc;
    cin>>cc;
    cout<<cc;
	return 0;
}

3.类型转换函数(类型转换运算符)

格式:

operator type(){
    //具体代码
    return data;
}
  • type 是要转换的目标类型,data 是要返回的 type 类型的数据。
  • 返回值data的类型和type目标类型必须是一样的。
    既然已经知道了要返回 type 类型的数据,所以没有必要再像普通函数一样明确地给出返回值类型。
  • 类型转换函数看起来没有返回值类型,其实是隐式地指明了返回值类型。
     
  • 类型转换函数也没有参数,因为要将当前类的对象转换为其它类型,所以参数不言而喻。
#include <iostream>
using namespace std;

class Complex
{
public:
    Complex(): real(0.0), imag(0.0){ }
    Complex(double real, double imag): real(real), imag(imag){ }
public:
    friend ostream & operator<<(ostream &out, Complex &c);
    //实现两个复数的相加
    friend Complex operator+(const Complex &c1, const Complex &c2);
    
    operator double() const { return real; }  //类型转换函数
private:
    double real;  //实部
    double imag;  //虚部
};

//重载>>运算符
ostream & operator<<(ostream &out, Complex &c)
{
    out << c.real <<" + "<< c.imag <<"i";;
    return out;
}
//重载+运算符
Complex operator+(const Complex &c1, const Complex &c2)
{
    Complex c;
    c.real = c1.real + c2.real;
    c.imag = c1.imag + c2.imag;
    return c;
}

int main()
{
    Complex c1(24.6, 100);
    double f = c1;  //相当于 double f = Complex::operator double(&c1);
    cout<<"f = "<<f<<endl;
 
    f = 12.5 + c1 + 6;  //相当于 f = 12.5 + Complex::operator double(&c1) + 6;
    cout<<"f = "<<f<<endl;
 
    int n = Complex(43.2, 9.3);  //先转换为 double,再转换为 int
    cout<<"n = "<<n<<endl;

    return 0;
}

 运行结果:

f = 24.6
f = 43.1
n = 43

注意:

  1. type 可以是内置类型、类类型以及由 typedef 定义的类型别名,任何可作为函数返回类型的类型(void 除外)都能够被支持。一般而言,不允许转换为数组或函数类型,转换为指针类型或引用类型是可以的。
  2. 类型转换函数一般不会更改被转换的对象,所以通常被定义为 const 成员。
  3. 类型转换函数可以被继承,可以是虚函数。
  4.  一个类虽然可以有多个类型转换函数(类似于函数重载),但是如果多个类型转换函数要转换的目标类型本身又可以相互转换(类型相近),那有时候就会产生二义性。例如:
    operator double() const { return m_real; }  //转换为double类型
    operator int() const { return (int)m_real; }  //转换为int类型

     那么下面的代码就会出错:

    Complex c(12.2, 30);
    float f = 1.1 + c;

    编译器可以调用 operator double() 将 c 转换为 double 类型,也可以调用 operator int() 将 c 转换为 int 类型,两种数据类型都可以和 1.1 进行加法运算。而且从 Complex 转换为 double 与从 Complex 转化为 int 是同级关系,没有谁的优先级是更高的。

也欢迎大家关注我的同名公众号获取更多信息和资料呀(^U^),欢迎大家在留言区交流。

以上是关于期末复习c++知识点大回顾,八篇文章让你永不破防(建议收藏)的主要内容,如果未能解决你的问题,请参考以下文章

期末复习c++知识点大回顾,八篇文章让你永不破防(建议收藏)

期末复习c++知识点大回顾,八篇文章让你永不破防(建议收藏)

期末复习c++知识点大回顾,八篇文章让你永不破防(建议收藏)

新星计划期末复习c++知识点大回顾,八篇文章让你永不破防(建议收藏)

C++类和对象期末复习笔记

大数据与云计算期末复习