JAVA/C++ 堆栈详解

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

最近在读《Thinking in Java 》,在博客上分享下笔记。小白入门,欢迎批评指正!

1. Java与C++在内存分配上的异同

内存区域共性C++Java
寄存器位于处理器内部,最快的存储区,由编译器根据需求进行分配,无法直接控制,也不能在程序中感觉到寄存器存在的任何迹象。C和C++允许向编译器建议寄存器的分配方式。
位于通用RAM中,由编译器自动分配释放,存放基本数据类型及对象引用等。创建程序时,系统知道存储在栈内的所有项的确切生命周期。C++的局部对象也分配在栈中,函数结束后对象被自动销毁。Java不允许创建局部对象,所以Java对象永远不可能存储于此
位于RAM区,供程序员分配的内存区域(new、malloc)C++中new、malloc创建的对象或分配的内存空间,使用完后必须手动释放delete、free,否则可能会出现内存泄漏Java中new出来的对象或数组。由JVM垃圾回收器进行管理,使用后无需手动释放。
其他静态区、文字常量区、程序代码区方法区(也叫静态区),存放整个程序中唯一的元素,如class和static变量,能被所有线程共享。

2. 局部对象(Java不运行创建局部对象)

局部对象是C++中的概念,指不是通过new的方式创建的对象,存储于栈中,随函数结束而销毁。Java不允许创建局部变量,故Java对象均存储在堆上。因此,C++中不要反悔局部对象的指针和引用(更具体地说,不能返回超过栈顶的对象的指针和引用)。可以返回的对象包括:
1. 通过new分配的对象
2. static对象
3. 函数调用之前创建的局部对象

举以下代码为例,可以看到,test0生命周期结束后,局部变量自动释放。

#include "iostream"
using namespace std;

class Person
{
    public:
        Person(int a);
        ~Person();
        int getId();

    private:
        int id;
};

Person::Person(int a)
{
    id = a;
}

Person::~Person()
{
    cout << "释放对象: "<< id << endl;
}

int Person::getId()
{
    return id;
}

/*返回局部对象的指针*/
Person *test0()
{
    Person *p = &Person(0);
    return p;
}
/*返回new创建的对象的指针*/
Person *test1()
{
    Person *p = new Person(1);
    return p;
}
/*返回static对象的指针*/
Person *test2()
{
    static Person temp(2);//在静态区创建的对象,随程序一起结束
    Person *p = &temp;  
    return p;
}

void main()
{
    Person *p0, *p1, *p2;
    p0 = test0();
    p1 = test1();
    p2 = test2();
    cout << "p0 ID: " << p0->getId() << endl;
    cout << "p1 ID: " << p1->getId() << endl;
    cout << "p2 ID: " << p2->getId() << endl;
    delete p1;
    cout << "p1 ID: " << p1->getId() << endl;
    //delete p2;  报错,不能delete静态对象
    system("pause");
}

输出:

释放对象: 0
p0 ID: 17047552
p1 ID: 1
p2 ID: 2
释放对象: 1
p1 ID: -572662307

3 C++堆内存可以手动释放,栈和静态区不能手动释放

c++ 栈中和静态区建立的对象都不能delete,因为栈和静态区都不是程序员直接可操作存储区。而java不存在这些说法,因为java对象都是new出来的(String似乎是个例外)。
参见以下代码,Person类不变。

    void main()
    {
        Person p0(0);
        static Person p1(1);
        Person *p2 = new Person(2);

        delete &p0;  //报错,栈局部对象
        delete &p1;  //报错,静态区对象
        delete p2;   //正确,堆对象
    }

4 总结

  1. 无论是java还是c++, 函数可以返回new出来的对象(确切说,存储在堆上的对象)的引用(或c++指针)
  2. c++不可以返回局部对象的引用或指针

参考文献
Think in Java
C/C++堆栈指引
深入理解Java的栈与堆栈

注意
JAVA中的数据存储(堆及堆栈)中所说的栈中数据共享似乎有误。

线程局部存储的来源?哪些编程语言支持线程局部存储TLS?堆栈 文章摘要: 本文介绍了线程局部存储(TLS)的概念及其在多线程编程中的重要性,列举了支持TLS的主流编程语言(C/C++Java/C#/Swift等)。同时探讨了堆栈的起源、地址随机化技术(ASLR)默认大小设置,比较了不同语言中变量的存储位置差异(如C/C++局部变量在堆栈Java/C#对象在中等)。最后提供了编程技术学习资源公众号推荐,适合开发者了解底层内存管理线程安全机制。(149字) 阅读详情

相关推荐

C++异常中的堆栈跟踪

C++异常中的堆栈跟踪 C++异常中的堆栈跟踪就是当程序抛出异常时,能够把抛出异常的语句所在的文件名、函数以及其它上层函数信息都打印出来。 堆栈跟踪意义重大:在实际的生产过程中,发现代码中bug要比解决bug更加费事费力,而发生异常时的堆栈信息可以帮助我们更快的发现程序中的问题,有助于加快开发。 C++不像java,在异常类中有提供堆栈跟踪功能,C++标准库中的std::exception及其子类...

sdjn_lyn的博客 3740

c++java的区别

首先两种不同语言的在操作方法的名字上有一些不同 首先看一下原c++的方法的基本用法:  push(): 向内压入一个成员;pop(): 从顶弹出一个成员;但不返回该顶值empty(): 如果为空返回true,否则返回false;top(): 返回顶,但不删除成员;size(): 返回内元素的大小;stack st; 方法:  1. public push  (item

qq_36734094的博客 607

java堆栈c++堆栈的区别

堆栈(stack)(heap)是应用程序中的两个地址空间,任何应用程序都有,语言无关。堆栈空间是编译期静态分配的,如果你有C++编译原理基础,看到程序就可以确定堆栈的分配情况了。空间是运行时动态分配的,在编译期没有办法确认分配空间的情况。它们的特点是:堆栈更快(如书上所说),但更灵活。 举个例子,假设A类有两个派生类(B,C),在Java中,你可以这么写: A a; char c ...

天涯明月刀的博客 1839

基于java的数据结构学习——数组实现的以及简单应用C++实现

基于java的数据结构学习——数组实现的以及简单应用C++ 实现 源码:   // // Created by PC-Saw on 2019/1/3. // #ifndef DATA_STRUCTURE_ARRAYSTACK_H #define DATA_STRUCTURE_ARRAYSTACK_H #include "Stack.h" #include "MyArray.h"...

believe_s的博客 277

java stl stack_C++标准库之stack

C++库以提供“模板”为主。所谓模板,是指不必预先制定类型的函数或类。我们可以借助STL(标准模板库Standard Template Library, STL)提供的高效算法来管理数据。为应对多种需求,STL为用户提供了多种名为容器(Container)的类,用于管理数据集合。在创建动态数组、表、、队列等数据结构时,我们只需要定义对应的容器,然后调用相应成员函数或算法即可。stack的成员函...

weixin_42137032的博客 264

javac++堆栈的故事

故事简介 c++是个向往自由的boy,他对堆栈的态度是:自由灵活。java认为生而为编程语言,就应该受到一定的约束才能更快活。于是他们堆栈便开始了扯不开的羁绊。 好了好了,引子介绍完了,开始正文。 创建对象 c++它创建对象可以在上创建也可以在上创建,java则所有的对象都在上创建。 c++的对象的创建 c++创建对象有两种方式,一种是动态在上创建: object *o = new ob...

Mr 羊的博客 250

Android Studio 2023.2 Logcat 实战:5步精准定位游戏空指针异常堆栈

本文详细介绍了如何使用Android Studio 2023.2的Logcat工具精准定位游戏开发中的空指针异常(NullPointerException)。通过5个实战步骤,包括配置日志环境、解读异常堆栈、动态调试、游戏场景解决方案构建防崩溃监控体系,帮助开发者快速解决游戏闪退问题,特别适用于Cocos2dx引擎场景。

332

javaC/C++的dump trace堆栈打印

1、Java dump backtrace方法: Log.e(TAG,Log.getStackTraceString(new Throwable())); 2、C++ dump backtrace方法:

luyao3038的博客 1438

cpp/java 函数调用 堆栈打印方法

cpp层打印调用 方法一 一、在需要加堆栈的文件(*.cpp)里 #if defined(ENABLE_MBACKTRACE) && (ENABLE_MBACKTRACE == 1) #include "MBacktrace.h" #endif 二、查找调用函数(此cpp的某个函数某个位置) #if defined(ENABLE_MBACKTRACE) &&amp...

JCYAO_的博客 1467

android 打印java堆栈,Android打印堆栈

java打印堆栈方法一:异常对象打印堆栈Exception e = new Exception("this is a log");e.printStackTrace();方法二:Log打印获取异常的堆栈并打印Log.e(“dump_test”,Log.getStackTraceString(new Throwable()));C++\C打印堆栈方法一:linux函数函数介绍头文件:java#inc...

weixin_29191761的博客 859

Java堆栈详解

1. Java堆栈(stack)(heap) (1)内存分配的策略    按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,式的,式的.   静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间.这种分配策略要求程序代码中不 允许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归的结构出现,因为

观千剑而后识器,操千曲而后晓声。 3600

Android 堆栈打印

Android 堆栈打印JavaC++层Kernel Java层 方式 一 Slog.d(TAG, Log.getStackTraceString(new Throwable())); 方式 二 Exception e = new Exception("this is a log"); e.printStackTrace(); 方式 三 RuntimeException e = new RuntimeException(); e.fillInStackTrace

zjbeaner的博客 500

android java 堆栈_Android下打印调试堆栈方法

android java 堆栈_Android下打印调试堆栈方法

Android framework 1218

java 打印堆栈_Java 打印堆栈的方法

方法一.Exception e = new Exception("this is a log"); //相应的log标记e.printStackTrace();//延迟才可以看出效果//Thread.currentThread().sleep(1000);//System.out.println("-------------以上是异常详细信息----------------");方法二 .Stri...

weixin_30635707的博客 1906

C++堆栈

 堆栈的概念(我的理解就是heap,就是stack,有别于有些人的提法:堆栈就是指stack)对于一个C++或者任何语言的程序员都是极度重要的,除非你是只准备停留在语言syntax层面的coder, 堆栈对于理解语言运行原理环境实在太重要,比如你在C++中只要写简单一句 int arr[1000000]; 你的程序肯定就会遇到运行时的错误报告,其实就是stack overflow, 要知道通

李丞的专栏 868

AppErrorsTracking 捕获 Native 层崩溃:JNI/C++ 异常堆栈追踪实战指南

AppErrorsTracking 是一款基于 Xposed 生态的 Android 应用崩溃捕获工具,不仅能记录 Java 层异常,更能抓取 **Native 层崩溃**,为开发者提供完整的 **JNI/C++ 异常堆栈追踪**信息——无需连接电脑、无需 ADB,在手机上即可快速定位崩溃根源。 ## 为什么 Native 崩溃堆栈很难排查? 当 App 通过 JNI 调用 C/C++ 代码,

gitblog_00399的博客 1045

android java 堆栈_Android下打印调试堆栈方法 | 学步园

打印堆栈是调试的常用方法,一般出现异常时,我们可以在跑出异常时也将堆栈情况打印出来,这样十分方便错误查找。另外实际上也有一个非常有用的功能:分析代码的行为。android代码太过庞大了,完全的静态分析经常是无从下手,因此通过打印堆栈的动态分析也十分必要。Android打印堆栈的方法,简单归类一下1. zygote的堆栈dump实际上这个可以同时dump java线程及native线程的堆栈,对于j...

weixin_39926540的博客 470

Android S上: C++java打印调用堆栈以及addr2line使用

1,C++打印调用堆栈: 1,C++打印调用堆栈: #include <utils/CallStack.h> CallStack stack("xxx"); shared_libs:["libutilscallstack"] C++堆栈log demo: C++堆栈log demo: log : #06 pc 00000000000a47d4 /system/lib64/libmediaplayerservice.so (android::StagefrightRecorder::stop

月山知了的博客 5841
上一篇: Visenze API
下一篇: 求二进制中1的个数
anyangchn
博客等级 码龄11年 1粉丝 3原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值