「C++系列」一篇文章说透【存储类】

文章目录

  • 一、C++ 存储类
    • 1. 类的定义
    • 2. 对象的创建
    • 3. 对象在内存中的布局
    • 4. 对象的存储位置
  • 二、auto 存储类
    • 1. `auto`的基本用法
    • 2. `auto`与存储类的关系
      • 1) 自动存储类(最常见的)
      • 2) 静态存储类
      • 3) 动态存储类(通过new)
  • 三、register 存储类
    • 1. register 存储类的特点
    • 2. 案例
    • 3. 注意事项
  • 四、static 存储类
    • 1. 局部静态变量
    • 2. 全局静态变量
    • 3. 静态类成员变量
    • 4. 静态类成员函数
  • 五、extern 存储类
    • 1. 声明全局变量
    • 2. 声明函数
    • 3. extern "C"
    • 4. 注意事项
  • 六、mutable 存储类
    • 1. 基本用法
    • 2. 示例
    • 3. 注意事项
  • 七、thread_local 存储类
    • 1. 基本用法
    • 2. 注意事项
  • 八、相关链接

在这里插入图片描述

一、C++ 存储类

在C++中,类的存储方式主要涉及到类的定义、对象的创建以及这些对象在内存中的布局。C++是一种静态类型、编译型语言,支持面向对象的编程范式。下面详细解释这些概念:

1. 类的定义

类是C++中用户定义的类型(UDT),用于封装数据(称为成员变量或属性)和函数(称为成员函数或方法)。类的定义不会为对象分配任何内存,它只是描述了对象的结构。

class MyClass {
public:int x;void func() {// 成员函数实现}
};

2. 对象的创建

当你使用类来创建对象时,才会在内存中为对象分配空间。这个空间用于存储对象的成员变量。成员函数则不直接存储在对象中,而是存储在程序的代码段中,对象通过其成员函数指针(通常是通过隐式的this指针)来访问这些函数。

MyClass obj; // 创建一个MyClass类型的对象obj

3. 对象在内存中的布局

  • 成员变量:对象的成员变量(包括从基类继承的成员变量)按照它们在类中声明的顺序,在内存中连续存储。成员变量的对齐和填充(padding)可能会根据编译器和平台的不同而有所不同,以优化内存访问速度。
  • 成员函数:成员函数不直接存储在对象中,而是存储在程序的代码段(Code Segment)中。当对象调用成员函数时,该函数通过隐式的this指针来访问对象的成员变量。
  • 静态成员:静态成员变量在程序的全局数据段中分配一次内存,所有对象共享同一份静态成员变量的拷贝。静态成员函数则不直接访问任何对象的成员变量(除非通过对象或类名显式传递),因此它们没有this指针。

4. 对象的存储位置

对象的存储位置取决于其生命周期和作用域:

  • 自动存储期:在函数或代码块内声明的局部变量(包括对象)存储在栈(Stack)上,其生命周期仅限于定义它们的代码块。
  • 静态存储期:全局对象、静态局部变量以及静态成员变量存储在全局数据段(Global Data Segment)或静态数据段(Static Data Segment)中,它们在程序的整个执行期间都存在。
  • 动态存储期:通过new操作符动态分配的对象存储在堆(Heap)上,其生命周期由newdelete操作符控制。

二、auto 存储类

在C++中,auto 关键字不是用来直接声明存储类的,而是用来自动推导变量类型的。存储类(也称为存储期或生命周期)指的是变量在内存中保留的时间长度,常见的存储类有自动(automatic)、静态(static)、寄存器(register,但现代C++中很少使用,且其优化行为通常由编译器自动处理)、外部(extern)以及动态分配(通过new操作符)。

然而,当我们在C++中使用auto关键字时,我们是在告诉编译器自动根据初始化表达式的类型来推导变量的类型。这并不意味着auto变量就有特定的存储类;它的存储类取决于其声明的上下文。

1. auto的基本用法

下面是一个使用auto的简单案例,它演示了如何自动推导变量的类型,但并没有直接涉及到存储类的概念:

#include <iostream>
#include <vector>int main() {// 自动推导为int类型auto a = 10;std::cout << "a is: " << a << std::endl;// 自动推导为std::vector<int>类型std::vector<int> v = {1, 2, 3, 4, 5};auto b = v; // 注意:这里b是v的一个拷贝,而不是引用std::cout << "b has " << b.size() << " elements." << std::endl;return 0;
}

2. auto与存储类的关系

尽管auto本身不直接声明存储类,但auto声明的变量可以根据其声明的上下文获得不同的存储类。以下是一些例子:

1) 自动存储类(最常见的)

void func() {auto x = 10; // x具有自动存储类,因为它是在函数内部声明的局部变量// ...
} // x的作用域结束,x的生命周期也结束

2) 静态存储类

static auto y = 20; // y具有静态存储类,尽管它是用auto声明的
// y的生命周期贯穿整个程序执行期间,但其作用域可能受限于声明它的块或文件void func() {// 可以在这里访问y
}

注意:在全局或命名空间作用域中使用static会改变链接性(linkage),但在函数内部使用时,它主要影响生命周期和初始化时机(只初始化一次)。

3) 动态存储类(通过new)

虽然auto通常不直接与动态分配相关联,但你可以使用auto来接收new表达式的结果:

auto ptr = new int(30); // ptr是指向int的指针,具有自动存储类
// 但它指向的对象是通过new动态分配的,具有动态存储类
// 记得用delete ptr;来释放内存

在这个例子中,ptr本身是一个具有自动存储类的局部变量,但它指向的对象是通过new动态分配的,因此该对象具有动态存储类。

总结:auto用于自动推导变量类型,而变量的存储类取决于其声明的上下文(如是否在函数内部、是否使用了static关键字、是否通过new动态分配等)。

三、register 存储类

在C++中,register 存储类是一个特殊的说明符,用于向编译器建议将变量存储在CPU的寄存器中,以便快速访问。然而,需要注意的是,register 关键字仅仅是一个建议,并不保证变量一定会被存储在寄存器中。此外,从C++11开始,register 关键字被废弃,现代编译器通常会忽略它,因为它们有自己的优化机制来决定变量的存储位置。

1. register 存储类的特点

  1. 建议性register 关键字告诉编译器,程序员认为该变量应该被频繁访问,因此建议将其存储在寄存器中。但编译器可以忽略这个建议。
  2. 局部变量register 只能用于局部变量,不能用于全局变量或静态变量。
  3. 限制:使用 register 的变量不能被取地址(即不能应用一元 & 运算符),因为它可能没有内存地址。
  4. 尺寸限制register 变量的最大尺寸通常等于寄存器的大小(通常是一个词或几个词)。

2. 案例

尽管 register 关键字在现代C++编程中不再被推荐使用,但以下是一个简单的例子,展示了如果编译器支持 register 关键字时它的用法:

#include <iostream>int main() {register int counter = 0; // 建议编译器将counter存储在寄存器中for (int i = 0; i < 1000000; i++) {counter++; // 假设counter被存储在寄存器中,这可能会提高循环的性能}std::cout << "Counter: " << counter << std::endl;return 0;
}

然而,在现代C++编译器中,即使你使用了 register 关键字,编译器也可能会忽略它,因为它有自己的优化策略来决定哪些变量应该被存储在寄存器中。

3. 注意事项

  • 废弃:由于 register 关键字在C++11中被废弃,因此在新的C++代码中应避免使用它。
  • 性能优化:如果你关心性能,并且想要优化特定变量的访问速度,最好让编译器自己处理这些优化,或者通过其他方式(如使用更高效的算法或数据结构)来提高程序性能。
  • 代码可读性:使用 register 关键字可能会降低代码的可读性,因为它引入了一个不再被现代编译器广泛支持的特性。

综上所述,虽然 register 存储类在理论上可以用于优化变量访问速度,但在现代C++编程中,它已经不再是一个有用的特性,应该被避免使用。

四、static 存储类

在C++中,static存储类是一个非常重要的特性,它用来控制变量的存储方式和可见性。以下是static存储类的详细解释:

1. 局部静态变量

static用于函数内的局部变量时,它会使该变量具有静态存储期,即变量在程序的整个执行期间都存在,但只在定义它的作用域内可见。这样的变量只初始化一次,每次函数调用时保留其最后一次使用的值。

特点

  • 存储在静态存储区。
  • 只在定义它的函数内可见。
  • 即使函数调用结束,也不会销毁。
  • 只初始化一次。

示例

#include <iostream>
using namespace std;void countFunction() {static int count = 0; // 局部静态变量count++;cout << "Count: " << count << endl;
}int main() {countFunction(); // 输出 1countFunction(); // 输出 2countFunction(); // 输出 3return 0;
}

2. 全局静态变量

在函数外部使用static声明的全局变量或函数,会限制其链接性(可见性),使其只在定义它的文件中可见。这有助于避免不同源文件之间的命名冲突。

特点

  • 存储在全局数据段。
  • 只在其定义的文件内可见。
  • 在程序的整个执行期间都存在。

示例

// file1.cpp
#include <iostream>
static int globalValue = 10;
void display() {std::cout << "Global Value in file1: " << globalValue << std::endl;
}// file2.cpp
// extern int globalValue; // 如果取消注释,则会导致编译错误,因为globalValue在file2中不可见// 假设有main函数在file2.cpp或其他地方
// 调用display函数会正常显示file1中的globalValue值

3. 静态类成员变量

在类中声明static变量时,该变量不属于任何特定的对象实例,而是类的所有实例共享的。它们必须在类外部初始化。

特点

  • 存储在静态存储区。
  • 类的所有对象共享同一份拷贝。
  • 初始化时使用作用域运算符(::)来标明它所属类。

示例

#include <iostream>
using namespace std;class MyClass {
public:static int staticValue;
};int MyClass::staticValue = 0; // 初始化int main() {MyClass obj1, obj2;obj1.staticValue = 5;cout << "Static Value from obj1: " << obj1.staticValue << endl; // 输出 5cout << "Static Value from obj2: " << obj2.staticValue << endl; // 输出 5return 0;
}

4. 静态类成员函数

静态成员函数与静态数据成员一样,都是类的内部实现,属于类定义的一部分。它们可以在没有对象实例的情况下调用,并且只能访问其类的静态成员。

特点

  • 没有this指针。
  • 只能访问类的静态成员变量和静态成员函数。

示例

#include <iostream>
using namespace std;class MyClass {
public:static int staticValue;static void displayValue() {cout << "Static Value: " << staticValue << endl;}
};int MyClass::staticValue = 10;int main() {MyClass::displayValue(); // 输出 10return 0;
}

五、extern 存储类

在C++中,extern关键字是一个非常重要的存储类修饰符,它主要用于声明一个全局变量或函数,这些变量或函数是在其他文件中定义的。下面详细解释extern存储类的用法和特点:

1. 声明全局变量

当我们在多个文件中使用同一个全局变量时,extern可以帮助我们实现这一目标。通过extern,我们可以在一个文件中声明该全局变量(而不是定义它,即不分配内存),然后在其他文件中使用它。这样做的好处是避免了在多个文件中重复定义同一个全局变量可能导致的编译错误。

示例

假设我们有两个文件,main.cppsupport.cpp

  • support.cpp中定义一个全局变量:
int testVar = 0; // 定义一个全局变量
  • main.cpp中,我们通过extern来声明这个全局变量,以便使用它:
extern int testVar; // 声明外部变量int main() {testVar = 10; // 使用外部变量// ...
}

2. 声明函数

除了变量之外,extern也可以用于声明在其他文件中定义的函数。这样,我们就可以在多个文件中调用同一个函数,而不需要在每个文件中都重复函数的定义。

示例

  • support.cpp中定义一个函数:
void testFunc() {// 函数体
}
  • main.cpp中,我们通过extern来声明这个函数,以便调用它:
extern void testFunc(); // 声明外部函数int main() {testFunc(); // 调用外部函数// ...
}

然而,需要注意的是,在C++中,对于函数的声明,extern通常是隐式的,即我们不需要显式地写出extern来声明一个函数是在其他文件中定义的。但在某些特殊情况下,为了强调或明确函数的外部链接性,也可以显式地使用extern

3. extern “C”

在C++中,我们还会经常看到extern "C"的用法。这是因为C++支持函数重载,而C语言不支持。当C++代码需要被C语言代码调用时,为了避免链接错误(即C++编译器对函数名进行名称修饰,而C编译器不进行),我们需要用extern "C"来告诉C++编译器按照C语言的方式来链接这些函数。

示例

extern "C" void testFunc() {// 函数体
}

或者,在头文件中声明时:

#ifdef __cplusplus
extern "C" {
#endifvoid testFunc();#ifdef __cplusplus
}
#endif

4. 注意事项

  • extern只是声明,不是定义。它告诉编译器变量或函数的类型,但不会分配内存。
  • extern声明的变量或函数必须在某个文件中被定义,否则在链接阶段会报错。
  • extern只能用于全局变量和函数,不能用于函数内部的局部变量。
  • 在C++中,对于函数的声明,extern通常是隐式的,但对于全局变量或需要明确指出外部链接性的函数,extern是必需的。

六、mutable 存储类

在C++中,mutable关键字是一个特殊的存储类修饰符,它用于类的成员变量上,以允许这个成员变量即使在常量成员函数(即被const修饰的成员函数)中也能被修改。这个特性在需要缓存计算结果、跟踪对象状态变化等场景中非常有用,特别是当这些变化不应该影响对象的逻辑常量性时。

1. 基本用法

当你将mutable关键字应用于类的成员变量时,这个成员变量即使在常量成员函数中也可以被修改。这意呀着,常量成员函数(即被声明为const的成员函数)可以修改这个mutable成员变量的值,而不会违反const成员函数不应修改任何成员变量的常规规则。

2. 示例

#include <iostream>class MyClass {
private:mutable int cache; // 使用mutable修饰,允许在const成员函数中被修改int value;public:MyClass(int v) : value(v), cache(-1) {} // 初始化value,cache初始化为-1表示未计算// 常量成员函数,但可以修改mutable成员变量cacheint getValue() const {if (cache == -1) { // 如果cache未被计算cache = computeValue(); // 计算并存储结果}return cache;}// 非const成员函数,可以修改所有成员变量void setValue(int v) {value = v;cache = -1; // 重置cache,因为value的改变可能影响计算结果}private:// 假设这是一个耗时的计算过程int computeValue() const {// ... 进行计算 ...return value * 2; // 仅为示例}
};int main() {MyClass obj(5);std::cout << "Value: " << obj.getValue() << std::endl; // 输出:Value: 10obj.setValue(10);std::cout << "New Value: " << obj.getValue() << std::endl; // 输出:New Value: 20return 0;
}

3. 注意事项

  • mutable只能用于类的成员变量上。
  • 使用mutable要谨慎,因为它可能会让代码的阅读者感到困惑,特别是当常量成员函数实际上修改了某些状态时。因此,建议只在确实需要时才使用mutable,并且确保在文档中清楚地说明这一点。
  • mutable成员变量通常用于缓存计算结果、状态跟踪等场景,这些场景中的变化不会影响对象的逻辑常量性。
  • mutable成员变量不会改变常量成员函数的const性质,即常量成员函数仍然不能修改类的非mutable成员变量。

七、thread_local 存储类

在C++11及以后的版本中,thread_local关键字被引入作为一个存储类修饰符,用于声明线程局部存储(Thread-Local Storage, TLS)的变量。这意味着每个线程都有该变量的一个独立实例,线程之间对这些变量的修改是互不影响的。

1. 基本用法

当你在变量声明前加上thread_local关键字时,这个变量就变成了线程局部的。每个线程对这个变量的访问都指向它自己的独立实例。

#include <iostream>
#include <thread>thread_local int tls_var = 0; // 线程局部变量void increment() {tls_var++; // 每个线程都会增加它自己的tls_var实例std::cout << "Thread " << std::this_thread::get_id() << " sees tls_var as " << tls_var << std::endl;
}int main() {std::thread t1(increment);std::thread t2(increment);increment(); // 主线程也会执行t1.join();t2.join();return 0;
}

在这个例子中,每个线程(包括主线程)都会打印出它自己的tls_var值,这些值在每次调用increment函数时都会递增,但每个线程看到的都是它自己的独立副本。

2. 注意事项

  • thread_local变量在其所属线程开始时被构造,在线程结束时被销毁。这意味着你不能在全局作用域中直接初始化一个需要构造函数和析构函数的thread_local变量,因为全局变量的构造和析构发生在程序开始和结束时,而这时线程可能还没有开始或已经结束。
  • thread_local变量不会跨线程共享,这意呀着每个线程对其的修改都不会影响到其他线程。
  • 在某些平台上,thread_local变量的实现可能依赖于动态内存分配,这可能会引入额外的性能开销。此外,如果线程数量非常多,可能会消耗大量的内存。
  • 在使用thread_local时,要特别注意内存泄漏和异常安全问题。如果thread_local变量在析构时抛出异常,并且这个异常没有被捕获,那么程序可能会以未定义的方式终止。
  • 并不是所有的C++实现都支持thread_local,但它被C++11标准所要求,因此大多数现代编译器都支持它。

八、相关链接

  1. Visual Studio Code下载地址
  2. Sublime Text下载地址
  3. 「C++系列」C++简介、应用领域
  4. 「C++系列」C++ 基本语法
  5. 「C++系列」C++ 数据类型
  6. 「C++系列」C++ 变量类型
  7. 「C++系列」C++ 变量作用域
  8. 「C++系列」C++ 常量知识点-细致讲解
  9. 「C++系列」C++ 修饰符类型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/870622.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C标准库读写文件

函数介绍 库变量 变量描述size_t无符号整数类型&#xff0c;是sizeof关键字的结果&#xff0c;表示对象大小FILE文件流类型&#xff0c;适合存储文件流信息的对象类型 库宏 宏描述NULL空指针常量EOF表示已经到达文件结束的负整数stderr、stdin、stdout指向FILE类型的指针&a…

【数智化案例展】吉林省消防救援总队——基于大语言模型的119智慧助手

‍ 嘉诚信息案例 本项目案例由嘉诚信息投递并参与数据猿与上海大数据联盟联合推出的《2024中国数智化转型升级创新服务企业》榜单/奖项评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 随着信息时代的迅猛发展&#xff0c;消防人员正面临前所未有的知识爆炸挑战。为了高…

day30--56. 合并区间+ 738.单调递增的数字

一、56. 合并区间 题目链接&#xff1a;https://leetcode.cn/problems/merge-intervals/ 文章讲解&#xff1a;https://programmercarl.com/0056.%E5%90%88%E5%B9%B6%E5%8C%BA%E9%97%B4.html 视频讲解&#xff1a;https://www.bilibili.com/video/BV1wx4y157nD 1.1 初见思路 …

数据库第四次练习

数据准备 创建两张表&#xff1a;部门&#xff08;dept&#xff09;和员工&#xff08;emp&#xff09;&#xff0c;并插入数据&#xff0c;代码如下 create table dept( dept_id int primary key auto_increment comment 部门编号, dept_name char(20) comment 部门名称 ); in…

SAP PS学习笔记02 - 网络,活动,PS文本,PS文书(凭证),里程碑

上一章讲了PS 的概要&#xff0c;以及创建Project&#xff0c;创建WBS。 SAP PS学习笔记01 - PS概述&#xff0c;创建Project和WBS-CSDN博客 本章继续讲PS的后续内容。包括下面的概念和基本操作&#xff0c;以及一些Customize&#xff1a; - 网络&#xff08;Network&#xf…

力扣-回溯法

何为回溯法&#xff1f; 在搜索到某一节点的时候&#xff0c;如果我们发现目前的节点&#xff08;及其子节点&#xff09;并不是需求目标时&#xff0c;我们回退到原来的节点继续搜索&#xff0c;并且把在目前节点修改的状态还原。 记住两个小诀窍&#xff0c;一是按引用传状态…

欣奇随机美图源码

欣赏养眼美图让人心情愉悦 新增正能量进站引导首页 上传文件解压即可用有手就行 美图输出接口自判断版 http://mt.xqia.net/api.php http://mt.xqia.net/api.php?typejson 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/89520368 更多资源下载&…

20240711每日消息队列-------------MQ消息的积压的折磨

目标 解决MQ消息的积压 背景 菜馆系统----------- 系统读取消息&#xff0c;处理业务逻辑&#xff0c;持久化订单和菜品数据&#xff0c;然后将其显示在菜品管理客户端上。 最初我们的用户基数很小&#xff0c;上线后的一段时间内&#xff0c;MQ消息通信还算顺利。 随着用户…

R包:‘ggcharts好看线图包‘

介绍 ggcharts提供了一个高级{ggplot2}接口&#xff0c;用于创建通用图表。它的目标既简单又雄心勃勃:让您更快地从数据可视化的想法到实际的绘图。所以如何?通过处理大量的数据预处理&#xff0c;为您模糊{ggplot2}细节和绘图样式。生成的图是ggplot对象&#xff0c;可以使用…

蓝桥 7.11 dp

2.砝码称重 - 蓝桥云课 (lanqiao.cn) 思路 动态规划的核心思想是将问题分解成更小的子问题&#xff0c;并存储子问题的解&#xff0c;以避免重复计算 数组 dp[i][j] 表示使用前 i 个砝码可以称出的重量为 j 的数量 更新过程如下&#xff1a; 1.初始化&#xff1a;dp[0][0] …

python:sympy 求解一元五次方程式

pip install sympy 或者 本人用的 anaconda 3 自带 sympy 在北大数学训练营&#xff0c;韦东奕 用卡丹公式 巧妙 求解一元五次方程式&#xff1a; \latex $x^510*x^320*x-4 0$ from sympy import *x symbols(x) expr x**5 10*x**3 20*x -4# 用卡丹公式 尝试化简 a sym…

【IOS】React Native之HelloWorld

RN搭建开发环境 rvm 安装3.2.2 brew install node18 brew install watchman# 使用nrm工具切换淘宝源 npx nrm use taobao# 如果之后需要切换回官方源可使用 npx nrm use npmnpm install -g yarnbrew install cocoapodsnpm uninstall -g react-native-cli react-native-communi…

<数据集>表情识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;2504张 标注数量(xml文件个数)&#xff1a;2504 标注数量(txt文件个数)&#xff1a;2504 标注类别数&#xff1a;7 标注类别名称&#xff1a;[Neutral, Happy, Angry, Fear, Sad, surprised, Disguist] 序号类别名…

开始Linux之路(暑假提升)

人生得一知己足矣&#xff0c;斯世当以同怀视之。——鲁迅 Linux操作系统简单操作指令 1、ls指令2、pwd命令3、cd指令4、mkdir指令(重要)5、whoami命令6、创建一个普通用户7、重新认识指令8、which指令9、alias命令10、touch指令11、rmdir指令 及 rm指令(重要)12、man指令(重要…

Transformer——多头注意力机制(Pytorch)

1. 原理图 2. 代码 import torch import torch.nn as nnclass Multi_Head_Self_Attention(nn.Module):def __init__(self, embed_size, heads):super(Multi_Head_Self_Attention, self).__init__()self.embed_size embed_sizeself.heads headsself.head_dim embed_size //…

【VSCode】设置背景图片

1.下载background插件&#xff1a;拓展程序→background→install安装→设置&#xff1a; 2.点击在 settings.json 中编辑&#xff1a; 3.将settings.json文件中所有代码注释&#xff0c;添加以下代码&#xff1a; {// 是否开启背景图显示"background.enabled": t…

【Linux杂货铺】1.环境变量

1.环境变量基本概念 环境变量&#xff08; environment variables &#xff09;一般是指在操作系统中用来指定操作系统运行环境的一些参数。如&#xff1a;我们在编写 C / C &#xff0b;代码的时候&#xff0c;在链接的时候&#xff0c;从来不知道我们的所链接的动态静态库在哪…

什么是Web3D?国内有哪些公司可以做?

Web3D 是一种基于网页的三维立体虚拟现实技术。利用计算机图形学、图像处理、人机交互等技术&#xff0c;将现实世界中的物体、场景或概念以三维立体的方式呈现在网页里。Web3D 技术可以让用户在任何时间、任何地点&#xff0c;通过互联网与虚拟世界进行互动&#xff0c;获得身…

昇思25天学习打卡营第1天|初步了解

1在昇思平台上申请过相关资源之后&#xff0c;将示例代码粘贴到输入框内。可以在下图中创建一个新的文档。 2不过初次运行的时候会遇到一个问题&#xff0c;点击运行的时候会出现新的输入框&#xff0c;而不是直接运行。遇到此问题等待就可以了&#xff0c;或者稍微等一下再运…

【JVM】对象的生命周期一 | 对象的创建与存储

Java | 对象的生命周期1-对象的创建与存储 文章目录 前言对象的创建过程内存空间的分配方式方式1 | 指针碰撞方式2 | 空闲列表 线程安全问题 | 避免空间冲突的方式方式1 | 同步处理&#xff08;加锁)方式2 | 本地线程分配缓存 对象的内存布局Part1 | 对象头Mark Word类型指针 P…