您好,欢迎来到二三四教育网。
搜索
您的当前位置:首页栈与堆、作用域与生存期

栈与堆、作用域与生存期

来源:二三四教育网
// correct
#include<iostream>
#include<math.h>
#include<stdlib.h>
using namespace std;

/* 几何形体处理程序: 
 * 输入若干个几何形体的参数,要求按面积排序输出。
 * 输出时要指明形状。
 * Input:
 * 第一行是几何形体数目n(不超过100)
 * 下面有n行,每行以一个字母c开头
 * 若 c 是 ‘R’ ,则代表一个矩形,本行后面跟着两个整数,分别是矩形的宽和高
 * 若 c 是 ‘C’ ,则代表一个圆,本行后面跟着一个整数代表其半径
 * 若 c 是 ‘T’ ,则代表一个三角形,本行后面跟着三个整数,代表三条边的长度
 * Output:
 * 按面积从小到大依次输出每个几何形体的种类及面积。
 * 每行一个几何形体,输 出格式为:
 * 形体名称:面积*/

class CShape{
    public:
    virtual double Area()=0;
    virtual void PrintInfo()=0;
};

class CRectangle:public CShape {
    int w,h;
    public:
    CRectangle(int x,int y):w(x),h(y){}
    double Area(){return w*h;}
    void PrintInfo(){cout<<"Rectangle:"<<Area()<<endl;}
};

class CCircle:public CShape{
    int r;
    public:
    CCircle(int x):r(x){}
    double Area(){return r*r*3.14;}
    void PrintInfo(){cout<<"Circle:"<<Area()<<endl;}
};

class CTriangle:public CShape{
    int a,b,c;
    public:
    CTriangle(int x,int y,int z):a(x),b(y),c(z){}
    double Area(){
        //海伦公式
        double p=double(a+b+c)/2;
        return sqrt(p*(p-a)*(p-b)*(p-c));
    }
    void PrintInfo(){cout<<"Triangle:"<<Area()<<endl;}
};

int MyCompare(const void* p1,const void* p2){
        CShape** pc1;
        CShape** pc2;
        pc1=(CShape**)p1;
        pc2=(CShape**)p2;
        double a1,a2;
        a1=(*pc1)->Area();
        a2=(*pc2)->Area();
        if(a1>a2) return 1;
        else if(a1<a2) return -1;
        else return 0; 
}

int main(){
    CShape* p[100];
    int n;
    int i;
    cin>>n;
    for(i=0;i<n;i++){
        char ch;
        cin>>ch;
        switch(ch){
            case 'R':{
                int w,h;
                cin>>w>>h;
                CRectangle* pr=new CRectangle(w,h);
                p[i]=pr;
                cout<<p[i]<<endl;
                break;}
            case 'C':{
                int r;
                cin>>r;
                CCircle* pc=new CCircle(r);
                p[i]=pc;
                cout<<p[i]<<endl;
                break;}
            case 'T':{
                int a,b,c;
                cin>>a>>b>>c;
                CTriangle* pt=new CTriangle(a,b,c);
                p[i]=pt;
                cout<<p[i]<<endl;
                break;}
            default:{break;}
        }
    p[0]->PrintInfo();
    }
    qsort(p,n,sizeof(CShape*),MyCompare);
    for(i=0;i<n;i++)
    {
        p[i]->PrintInfo();
    }
    return 0;
}

若将case里程序实现改为新建派生类对象,然后将指针指向该对象方式,会发现p[i]里存放的地址相同,结果会出错

// wrong answer
int main(){
    CShape* p[100];
    int n;
    int i;
    cin>>n;
    for(i=0;i<n;i++){
        char ch;
        cin>>ch;
        switch(ch){
            case 'R':{
                int w,h;
                cin>>w>>h;
                //CRectangle* pr=new CRectangle(w,h);
                CRectangle CR(w,h);
                p[i]=&CR;
                cout<<p[i]<<endl;
                break;}
            case 'C':{
                int r;
                cin>>r;
                //CCircle* pc=new CCircle(r);
                CCircle CC(r);
                p[i]=&CC;
                cout<<p[i]<<endl;
                break;}
            case 'T':{
                int a,b,c;
                cin>>a>>b>>c;
                //CTriangle* pt=new CTriangle(a,b,c);
                CTriangle CT(a,b,c);
                p[i]=&CT;
        cout<<p[i]<<endl;
                break;}
            default:{break;}
        }
    p[0]->PrintInfo();
    }
    qsort(p,n,sizeof(CShape*),MyCompare);
    for(i=0;i<n;i++)
    {
        p[i]->PrintInfo();
    }
    return 0;
}

原因分析

新建的派生类对象为栈对象,case结束后会自动调用析构函数析构;
而new出来的为堆对象,需要delete析构。

C++内存分配方式

在C++中,内存分成5个区,分别是堆、栈、自由存储区、全局/静态区和常量存储区。
栈:
存放函数参数以及局部变量,在出作用域时,将自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但分配的内存容量有限。
堆:
new分配的内存块(包括数组,类实例等),需delete手动释放。如果未释放,在整个程序结束后,OS会帮你回收掉。
自由存储区:
malloc分配的内存块,需free手动释放。它和堆有些相似。
全局/静态区:
全局变量(global)和静态变量(static)存于此处。(在以前的C语言中,全局变量又分为初始化的和未初始化的,C++不分)
常量存储区:
常量(const)存于此处,此存储区不可修改。

栈与堆的区别

主要区别:
管理方式不同:
栈是编译器自动管理的,堆需手动释放。
空间大小不同::
在32位OS下,堆内存可达到4GB的的空间;而栈就小得可怜。(VC6中栈默认大小是1M,当然可以修改它)
能否产生碎片不同:
对于栈来说,进栈/出栈都有着严格的顺序(先进后出),不会产生碎片;而堆频繁的new/delete,会造成内存空间的不连续,容易产生碎片。
生长方向不同:
栈向下生长,以降序分配内存地址;堆向上生长,以升序分配内在地址。
分配方式不同:
堆动态分配,无静态分配;栈分为静态分配和动态分配。
分配效率不同:
栈是系统提供的数据结构,计算机会在底层对栈提供支持,进栈/出栈都有专门的指令,这就决定了栈的效率比较高;堆则不然,它由C/C++函数库提供,机制复杂,堆的效率要比栈低得多。

可以看出,栈的效率要比堆高很多,所以,尽量用栈。不过,虽然栈有如此多的好处,但远没有堆使用灵活。

作用域和生存期

作用域,顾名思义,就是作用的区域,分为函数原型作用域,局部作用域,类作用域和命名空间作用域。它们的作用范围按此顺序变大。

生存期,顾名思义,就是生存的时间,分为静态生存期和动态生存期。静态生存期有两种情况:1.命名空间作用域中的变量具有静态生存期;2.在局部作用域中用static声明的变量也具有静态生存期。除了这两种情况之外的变量都具有动态生存期。

在局部作用域中声明的变量如果用static修饰,则具有静态生存期,注意,虽然在整个程序中这个变量都存在,但它的作用域还是原来的作用域,而且这个变量叫做静态局部变量,也就是说生存期和作用域没有关系。

本文如未解决您的问题请添加抖音号:51dongshi(抖音搜索懂视),直接咨询即可。

热门图文

Copyright © 2019-2025 how234.cn 版权所有 赣ICP备2023008801号-2

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务