我知道“可变”和“不可变”是应该用来描述对象改变诸如Java和Objective
C之类的面向对象语言中的值的能力的术语。但是,我想提出它,因为它与我的语言有关有关原始数据的问题。我知道,当我更改持有不可变对象的变量的值时,实际上是在创建一个新对象。但是,我想知道C中的基本数据的行为是否类似于不可变对象。我的意思是,当我更改保存原始数据的变量的值时,将创建新数据并由该变量引用。还是现有的原语实际上改变/修改了存储的数据值?
编辑#1:
问题#1: 我想消除一些误解(无论是我本人还是其他人),因为当我说“当我更改持有不可变对象的变量的值时,我实际上是在创建一个新对象。”
当我这么说时,我并不是要将变量分配给现有对象。例如:
// Example 1: I did not mean this
-------------------------
String x = "Hello World";
String y = x;
-------------------------
// Example 2: What I meant is this
-------------------------
String x = "Hello World";
//This will print out "Hello World"
System.out.println(x);
x = "Goodbye World";
//This will print out "Goodbye World"
System.out.println(x);
-------------------------
当然,就像示例1中那样,将变量y分配给变量x,这就是你们提出的情况,只将变量y引用给x所引用的对象。当然,在这种情况下,没有新对象。只是同一对象“
Hello World”被两个变量引用。
我的意思是,在示例2中,当x =“ Goodbye World”时,变量x引用一个具有值“ Goodbye
World”的新String对象,而不是用x初始化的第一个String对象“ Hello
World”。字符串是Java中的不可变对象。更改String变量的值的唯一方法是让变量引用现有对象 或 新的String对象。如果没有现有对象(“
Goodbye World” String对象尚未在任何地方创建),则以上代码仅创建了一个新的String对象,并对其引用了x。我对吗?如果没有,请纠正我。
问题2: 我想总结一下答案,尤其是来自 Ulfalizer 的答案:
1)实际上,变量可以存在2种形式:
a)“内存地址”-对于C语言变量以及Java和Objective C有关原始类型数据的情况就是如此。例如:int x
=1。这里的变量x是一个实际的内存地址本身,它的类型为integer,并用值1初始化。
b)“参考”-对于非原始类型数据(对象),Java中的大多数变量都是这种情况。例如:String x =“ Hello
World”。变量x只是指向“存在于某处的内存地址”的指针/引用,其内容为“ Hello World”值。
2)C,Java和目标C中的原始类型数据的变量充当“内存地址”。因此,当我这样做时:
-------------------------
int x = 10;
x = 2;
-------------------------
x变量的值(又名-内存地址)实际上从10更改为2。换句话说,可以修改/更改存储在“ Memory Address”变量中的值。
3)在C语言中,如果变量以’‘-指针类型声明,则它也可以充当引用。我将使用 Ulfalizer* 的示例:int * ptr。ptr是一个指针变量,可以指向另一个变量(即内存地址),例如:ptr =&x。如果x初始化为:int x =
10,则x是保存值为10的实际内存地址。因此在下面的代码中
-------------------------
int x;
int *ptr;
ptr = &x;
*ptr = 1;
-------------------------
我实际上可以通过ptr指针变量修改存储在x变量(又名-内存地址)中的值。
请确认我的解释是否正确/错误。谢谢。
理解C的工作方式的最佳方法是将其视为高级汇编语言。变量只是内存中的位置,将值分配给变量会将值存储到该位置。从高级语言的角度来看,这将是最纯粹形式的变异。
在C中,声明/定义如
int x;
告诉编译器为该int
变量保留一些内存x
。(在函数内部,内存将来自堆栈。在全局范围内,它将来自数据段。)
像这样的作业
x = 7;
只需生成代码即可将值7复制到该内存位置。同样,类似
x = y;
生成代码以将int
存储在y
的存储位置的值复制到x
的存储位置。(假设y
是另一个int
。)
同样的逻辑也适用于比int
s 更复杂的类型。
在Java中,变量是引用(反正是非原始类型),并且可以在不同时间引用不同的对象。为了获得类似于C中引用的内容,您必须显式定义一个 指针
变量(一个保存地址的变量),并在不同的时间将其指向不同对象的地址(为其分配地址)。
(为方便起见,我提供了以下示例。)
的&
操作者用来得到在C变量的地址,以便&x
将地址x
例如。*
当应用于指针时,运算符将提供指向的对象。这是一个如何在不同时间使用指针来引用不同变量的示例:
int x;
int y;
/* Declares 'ptr' as a pointer, and says that it points to an int.
The pointed-to type is used by the compiler for type checking
and type conversions. */
int *ptr;
ptr = &x; // Store the address of 'x' in 'ptr'.
*ptr = 1; // Store 1 into the memory 'ptr' points to ('x').
ptr = &y; // Store the address of 'y' in 'ptr'.
*ptr = 2; // Store 2 into the memory 'ptr' points to ('y').
上面代码的最终结果将设置x
为1和y
2。这当然是一个愚蠢的示例,但希望它能使您理解。
(//
顺便说一下,C99和更高版本支持样式注释。)
(注意:我的Java有点生锈,因此我必须做一些阅读。希望细节应该正确。请随时纠正我。)
那作业
x = "Goodbye World";
将具有x
引用String
值为“再见世界” 的对象的效果。确切地说
,String
创建此对象的时间不应该有所不同,只要在分配给对象x
(或任何其他变量)之前创建该对象即可。
它可能是在执行分配之前或程序启动时创建的。通常,您将无法分辨出差异。
听起来您已经掌握了高级概念,并且您的C代码是正确的。
(尽管说“ ptr
是一个指针”比说“ *ptr
是一个指针”
更正确。C中存在一些语法上的晦涩之处,这使得*
在声明(IMO)中放置下一个名称更为自然,但是您可以也要像这样写声明int* ptr;
。只有在同一行中声明许多变量时,事情才开始变得怪异。)
在讨论Java的实现方式时,引用可能必须比仅是底层对象的指针要先进一些。例如,JVM可能会在内存中移动对象(这将更改它们的地址)以减少内存碎片,但是引用仍必须保持有效。一种方法是在移动对象时“固定”指针,另一种方法是使引用成为指针表的索引。不管它在JVM实现中是如何完成的,
指针 至少都是正确的想法。
由于Java中的每个引用都有一个指针字段(在高层,完全忽略了实现的方式),并且由于原始类型不需要此字段,因此一种可能性是重用指针字段并将值存储在其中而不是原始类型。
例如,类似
x = 1;
可能将值1直接存储到引用的指针字段中x
。这样的技术很普遍。
附带说明一下,a union
可以用于在C中将两种不同类型(例如,an
int
和指针)存储在内存中的同一位置,以便它们重叠。当然,分配给其中一种类型也会改变另一种类型的值。
问题内容: 我知道供应商有自己的原始SQL语言子集,这些子集用C(类似于Postgre SQL)或MS-SQL Server(C ++)等编写。 那么,原始的SQL是用C编写的,还是在Assembly中创建的呢?我真的找不到关于其原始语言根源的明确答案(除了历史等) 问题答案: 在Oracle上进行的快速历史搜索得出: 在70年代后期,Ingres刚开始在加州大学伯克利分校工作时,三个从事CIA合
本文向大家介绍易语言常量的值是否可以被改变,包括了易语言常量的值是否可以被改变的使用技巧和注意事项,需要的朋友参考一下 常量是指一个固定的量,它的值无法改变。我们可以通过易语言的支持库面板查找各种常量。 查看其中一个常量,如“黑色”,按下“F1”键或鼠标单击“提示”,可以看到黑色常量的说明信息。 其中值为0,表示调用0,就能显示黑色。如“标签1.背景颜色=0”,就是指标签框的背景颜色为黑色。 标签
问题内容: 如果方法具有局部变量: 然后分配一个新值: 这会分配一个新的内存位置吗?还是只替换原始值? 这是否意味着基元是不可变的? 问题答案: 这会分配一个新的内存位置吗?还是只替换原始值? Java并没有真正保证变量将与内存位置相对应。例如,如果编译器发现您从未真正使用过它的值,或者如果它可以在代码中进行跟踪,则您的方法可能以存储在寄存器中的方式进行了优化,或者甚至根本不存储。直接使用适当的值
在讲解变量之前,我们先来看一段代码: int x; int y=0; char z='A'; x=6; 在上面这段代码中出现的 x、y、z 都是一个 C 变量。 变量是编程语言中不可或缺的组成部分。它承载这存贮数据以及计算结果等等功能,顾名思义变量就是可以再计算执行过程中变化的量。这节课我们来学习下到底什么是变量。 1. 什么是变量? 变量是程序用来保存计算结果的存储单元,为了方便访问这块存储单
仓颉是前端语言还是后端语言?
问题内容: 我只是想知道Swift是像php一样的动态还是静态的,我的意思是我可以在应用程序运行时生成类吗? 问题答案: 它是静态的-非常静态。编译器必须有关于所有类和功能的全部信息 在编译时 。您可以(使用)“扩展”现有的类,但是即使那样,您也必须在编译时完全定义该扩展所包含的内容。 Objective-C是动态的,并且在现实生活中,由于您可能会在Cocoa的存在下使用Swift,因此可以使用O