这是一个简单的代码片段,这让我有点困惑:
string s1 = "abc";
string s2 = s1;
s2 = "123";
Debug.Log(s1 + ":" + s2);
Run Code Online (Sandbox Code Playgroud)
调试结果为abc:123
那么为什么s1没有更新为123,因为s1和s2包含相同的引用,如果一个变量更新它,则第二个将自动更新.
这是对参考文献使用的常见误解.
s1是引用类型,但其内容是值.您可以认为所有变量都是值类型,但编译器处理它们的方式因值或引用类型而异.
string s1 = "abc";
Run Code Online (Sandbox Code Playgroud)
s1等于存储"abc"的地址,假设为0x0000AAAA
string s2 = s1;
Run Code Online (Sandbox Code Playgroud)
s2指向与s1相同的地址,因此其值与s1相同.两者都具有值0x000AAAA
s2 = "123";
Run Code Online (Sandbox Code Playgroud)
字符串是不可变的,意味着你不能修改字符串,无论何时你分配一个新的值或修改,你在内存中的其他地方创建一个新字符串,而前一个字符串准备好GC,如果需要(实际上不是我们的情况).此时,s1仍然具有值0x0000AAAA,而s2具有新的0X0000BBBB.
Debug.Log(s1 + ":" + s2);
Run Code Online (Sandbox Code Playgroud)
由于两个点都在不同的内容,它们打印出不同的结果.
它只是一个引用类型,因为变量中包含的值并不是按原样使用,而是用于将指针发送到存储实际对象的内存中的地址位置.
除非你使用out/ref(&在C++中),否则暗示要使用变量的值(地址),最有可能作为参数.
请注意,此行为与任何对象相同,而不仅仅是字符串.
Dog dogA = new Dog();
Dog dogB = dogA;
dogA.name = "Wolfie"; // Affect both since we are dereferencing
dogA = new Dog(); // dogA is new object, dogB is still Wolfie
Run Code Online (Sandbox Code Playgroud)
编辑:OP需要解释ref/out.
当您想要更改对象时,您会想到以下内容:
void ChangeObject(GameObject objParam)
{
objParam = new GameObject("Eve");
}
void Start(){
GameObject obj = new GameObject("Adam");
ChangeObject(obj);
Debug.Log(obj.name); // Adam...hold on should be Eve (??!!)
}
Run Code Online (Sandbox Code Playgroud)
ChangeObject获取GameObejct作为参数,编译器将obj(00000AAAA)中包含的值复制到objParam上,它复制它并且两者现在具有相同的值.
在该方法中,objParam被赋予一个新值,并且与该方法之外的obj不再相关.objParam是方法的本地,并在完成时被删除(游戏对象仍在场景中,但引用丢失).
如果您希望在方法中更改obj:
void ChangeObject(ref GameObject objParam)
{
objParam = new GameObject("Eve");
}
void Start(){
GameObject obj = new GameObject("Adam");
ChangeObject(ref obj);
Debug.Log(obj.name); // Yeah it is Eve !!!
}
Run Code Online (Sandbox Code Playgroud)
这一次,它不是传递的obj的值,而是obj的地址.因此obj可能包含0x0000AAAA,但它自己的地址是0x0000AABB,然后objParam的值现在是0x0000AABB,更改objParam意味着更改存储在0x0000AABB的值.
out和ref的工作方式相同,只有那个需要在方法中分配一个值,而ref可以离开方法而不影响给定的参数.
| 归档时间: |
|
| 查看次数: |
1652 次 |
| 最近记录: |